[Libreoffice-commits] core.git: 8 commits - basegfx/source include/basegfx include/svx officecfg/registry svx/sdi svx/source sw/inc sw/sdi sw/source sw/uiconfig xmloff/source
Armin Le Grand
Armin.Le.Grand at cib.de
Fri Oct 20 12:45:14 UTC 2017
basegfx/source/matrix/b2dhommatrixtools.cxx | 43
include/basegfx/matrix/b2dhommatrixtools.hxx | 8
include/svx/svdobj.hxx | 4
include/svx/svdovirt.hxx | 3
include/svx/svxids.hrc | 2
officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu | 8
svx/sdi/svx.sdi | 17
svx/source/sidebar/possize/PosSizePropertyPanel.cxx | 1
svx/source/svdraw/svddrgmt.cxx | 487 +++-------
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 | 14
sw/sdi/grfsh.sdi | 9
sw/source/core/doc/notxtfrm.cxx | 39
sw/source/core/draw/dflyobj.cxx | 160 +++
sw/source/core/draw/dview.cxx | 24
sw/source/core/frmedt/feshview.cxx | 23
sw/source/core/inc/dflyobj.hxx | 13
sw/source/core/inc/frmtool.hxx | 7
sw/source/ui/frmdlg/frmpage.cxx | 31
sw/source/uibase/frmdlg/frmmgr.cxx | 24
sw/source/uibase/inc/frmmgr.hxx | 3
sw/source/uibase/inc/frmpage.hxx | 6
sw/source/uibase/shells/frmsh.cxx | 17
sw/source/uibase/shells/grfsh.cxx | 189 ++-
sw/uiconfig/sglobal/menubar/menubar.xml | 1
sw/uiconfig/sglobal/popupmenu/graphic.xml | 1
sw/uiconfig/sglobal/toolbar/graphicobjectbar.xml | 1
sw/uiconfig/sweb/menubar/menubar.xml | 1
sw/uiconfig/sweb/popupmenu/graphic.xml | 1
sw/uiconfig/swform/menubar/menubar.xml | 1
sw/uiconfig/swform/popupmenu/graphic.xml | 1
sw/uiconfig/swform/toolbar/graphicobjectbar.xml | 1
sw/uiconfig/swreport/menubar/menubar.xml | 1
sw/uiconfig/swreport/popupmenu/graphic.xml | 1
sw/uiconfig/swreport/toolbar/graphicobjectbar.xml | 1
sw/uiconfig/swriter/menubar/menubar.xml | 1
sw/uiconfig/swriter/popupmenu/graphic.xml | 1
sw/uiconfig/swriter/toolbar/graphicobjectbar.xml | 2
sw/uiconfig/swriter/ui/notebookbar.ui | 26
sw/uiconfig/swriter/ui/notebookbar_groupedbar_compact.ui | 7
sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui | 7
sw/uiconfig/swriter/ui/picturepage.ui | 149 +++
sw/uiconfig/swxform/menubar/menubar.xml | 1
sw/uiconfig/swxform/popupmenu/graphic.xml | 1
sw/uiconfig/swxform/toolbar/graphicobjectbar.xml | 3
xmloff/source/text/XMLTextFrameContext.cxx | 5
49 files changed, 1021 insertions(+), 419 deletions(-)
New commits:
commit 387554ef787ced5d3e5c94bb824aa5dc383f133a
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 7db8e4946abd..0935ddbd637c 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 9743ecb42095b6e742ab7636ccc67b820f8b9fee
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 d7c995ef552e..7db8e4946abd 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 c73238be62ea..7cd7c2702333 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 0914846b7857..23857b2b4745 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 93f5800e181372d3e5f02c825fd3b09f2756cac7
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"/>
commit 73360bdf0b60370c76d9669502c2b0e5a9d4e504
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Fri Sep 29 10:42:43 2017 +0200
RotGrfFlyFrame: Implemented Handle Update on rotation change
WIth rotaiton being allowed the handle visualisation may be
dependent on this, so it is necessary to refresh their
visualisation on rotation chnage, e.g. for crop handles
Change-Id: I218e326894999381fc4058b7eba432491a0cf23b
diff --git a/include/basegfx/matrix/b2dhommatrixtools.hxx b/include/basegfx/matrix/b2dhommatrixtools.hxx
index e462bad54b8e..3bc3627dfbf5 100644
--- a/include/basegfx/matrix/b2dhommatrixtools.hxx
+++ b/include/basegfx/matrix/b2dhommatrixtools.hxx
@@ -229,6 +229,7 @@ namespace basegfx
const B2DVector& getScale() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maScale; }
const B2DVector& getTranslate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maTranslate; }
double getRotate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfRotate; }
+ double getShearX() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfShearX; }
};
} // end of namespace utils
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index 72279ec410a8..3348579bd508 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -595,14 +595,14 @@ void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
{
// do something special since the object size is in the polygon
// break up matrix to get the scale
- const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aObjectTransform);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aObjectTransform);
// get polygon's position and size
const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange());
// get the scaling factors (do not mirror, this is in the object transformation)
- const double fScaleX(fabs(aDecomp.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
- const double fScaleY(fabs(aDecomp.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
+ const double fScaleX(fabs(aTmpDecomp.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
+ const double fScaleY(fabs(aTmpDecomp.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
// prepare transform matrix for polygon
basegfx::B2DHomMatrix aPolyTransform(
@@ -3657,16 +3657,16 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon);
{ // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
- const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aOriginalMatrix);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aOriginalMatrix);
- if(!basegfx::fTools::equalZero(aDecomp.getShearX()))
+ if(!basegfx::fTools::equalZero(aTmpDecomp.getShearX()))
{
bShearCorrected = true;
aOriginalMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aDecomp.getScale(),
- -aDecomp.getShearX(),
- aDecomp.getRotate(),
- aDecomp.getTranslate());
+ aTmpDecomp.getScale(),
+ -aTmpDecomp.getShearX(),
+ aTmpDecomp.getRotate(),
+ aTmpDecomp.getTranslate());
}
}
@@ -3740,13 +3740,13 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
// aDiscreteChangeMatrix, go to concrete sizes now.
// Create the unrotated original rectangle and the unrotated modified
// rectangle as Ranges
- const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aOriginalMatrix);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aOriginalMatrixDecomp(aOriginalMatrix);
// prepare unsheared/unrotated versions of the old and new transformation
const basegfx::B2DHomMatrix aOriginalMatrixNoShearNoRotate(
basegfx::utils::createScaleTranslateB2DHomMatrix(
- basegfx::absolute(aDecomp.getScale()),
- aDecomp.getTranslate()));
+ basegfx::absolute(aOriginalMatrixDecomp.getScale()),
+ aOriginalMatrixDecomp.getTranslate()));
// create the ranges for these
basegfx::B2DRange aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
@@ -3784,13 +3784,13 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
if(bShearCorrected)
{
// back-correct shear
- const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aNewObjectMatrix);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aNewObjectMatrix);
aNewObjectMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aDecomp.getScale(),
- -aDecomp.getShearX(),
- aDecomp.getRotate(),
- aDecomp.getTranslate());
+ aTmpDecomp.getScale(),
+ -aTmpDecomp.getShearX(),
+ aTmpDecomp.getRotate(),
+ aTmpDecomp.getTranslate());
}
// apply change to object by applying the unit coordinate change followed
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 6a23088246c4..a1154b2977d5 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -626,6 +626,27 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
GetItemState( n, false ))
{
CLEARCACHE
+
+ if(RES_GRFATR_ROTATION == n)
+ {
+ // RotGrfFlyFrame: Update Handles in view, these may be rotation-dependent
+ // (e.g. crop handles) and need a visualisation update
+ if ( GetNode()->GetNodeType() == SwNodeType::Grf )
+ {
+ SwGrfNode* pNd = static_cast<SwGrfNode*>( GetNode());
+ SwViewShell *pVSh = pNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
+
+ if(pVSh)
+ {
+ SdrView* pDrawView = pVSh->GetDrawView();
+
+ if(pDrawView)
+ {
+ pDrawView->AdjustMarkHdl(nullptr);
+ }
+ }
+ }
+ }
break;
}
if( RES_GRFATR_END == n ) // not found
commit a6fc51cbe40b98674ade29e090f1b45e1f530062
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 28 13:08:35 2017 +0200
RotGrfFlyFrame: Encapsulated matrix decomposes
Change-Id: I432766970ef06c7d85a0056d3f24280cf2acd47d
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index 90a6ad41f452..72279ec410a8 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -595,21 +595,20 @@ void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
{
// do something special since the object size is in the polygon
// break up matrix to get the scale
- basegfx::B2DTuple aScale;
- basegfx::B2DTuple aTranslate;
- double fRotate, fShearX;
- aObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aObjectTransform);
// get polygon's position and size
const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange());
// get the scaling factors (do not mirror, this is in the object transformation)
- const double fScaleX(fabs(aScale.getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
- const double fScaleY(fabs(aScale.getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
+ const double fScaleX(fabs(aDecomp.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
+ const double fScaleY(fabs(aDecomp.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
// prepare transform matrix for polygon
- basegfx::B2DHomMatrix aPolyTransform(basegfx::utils::createTranslateB2DHomMatrix(
- -aPolyRange.getMinX(), -aPolyRange.getMinY()));
+ basegfx::B2DHomMatrix aPolyTransform(
+ basegfx::utils::createTranslateB2DHomMatrix(
+ -aPolyRange.getMinX(),
+ -aPolyRange.getMinY()));
aPolyTransform.scale(fScaleX, fScaleY);
// transform the polygon
@@ -3658,18 +3657,16 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon);
{ // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
- basegfx::B2DTuple aScale, aTranslate;
- double fRotate(0.0), fShearX(0.0);
- aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aOriginalMatrix);
- if(!basegfx::fTools::equalZero(fShearX))
+ if(!basegfx::fTools::equalZero(aDecomp.getShearX()))
{
bShearCorrected = true;
aOriginalMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale,
- -fShearX,
- fRotate,
- aTranslate);
+ aDecomp.getScale(),
+ -aDecomp.getShearX(),
+ aDecomp.getRotate(),
+ aDecomp.getTranslate());
}
}
@@ -3743,17 +3740,13 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
// aDiscreteChangeMatrix, go to concrete sizes now.
// Create the unrotated original rectangle and the unrotated modified
// rectangle as Ranges
- basegfx::B2DTuple aScale, aTranslate;
- double fRotate, fShearX;
-
- // get access to scale and translate
- aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aOriginalMatrix);
// prepare unsheared/unrotated versions of the old and new transformation
const basegfx::B2DHomMatrix aOriginalMatrixNoShearNoRotate(
basegfx::utils::createScaleTranslateB2DHomMatrix(
- basegfx::absolute(aScale),
- aTranslate));
+ basegfx::absolute(aDecomp.getScale()),
+ aDecomp.getTranslate()));
// create the ranges for these
basegfx::B2DRange aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
@@ -3791,16 +3784,13 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
if(bShearCorrected)
{
// back-correct shear
- basegfx::B2DTuple aScale;
- basegfx::B2DTuple aTranslate;
- double fRotate(0.0), fShearX(0.0);
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomp(aNewObjectMatrix);
- aNewObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
aNewObjectMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale,
- -fShearX,
- fRotate,
- aTranslate);
+ aDecomp.getScale(),
+ -aDecomp.getShearX(),
+ aDecomp.getRotate(),
+ aDecomp.getTranslate());
}
// apply change to object by applying the unit coordinate change followed
commit d9b16effeda21488911d1b5035f9d3be05731ca2
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Sep 28 10:20:15 2017 +0200
RotGrfFlyFrame: Adapt Crop functionality to rotated Graphic
The FlyFrame which may contain a Graphic needs working Crop,
interactive and in core. Adapted this to work with now possible
rotation, changed common code in svx which has to handle cases
for Draw/Impress/Calc and Writer differently. Tried to use as
much in common as possible. Additionally furter adaptions
to rotation itself.
Change-Id: Ia961e9490e2627c74220b186116f5aa4fcabca78
diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx b/basegfx/source/matrix/b2dhommatrixtools.cxx
index a267b05b96d1..26936aff2e5c 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -358,6 +358,48 @@ namespace basegfx
return aRetval;
}
+ BASEGFX_DLLPUBLIC B2DHomMatrix createRotateAroundCenterKeepAspectRatioStayInsideRange(
+ const basegfx::B2DRange& rTargetRange,
+ double fRotate)
+ {
+ basegfx::B2DHomMatrix aRetval;
+
+ // RotGrfFlyFrame: Take rotation into account. Rotation is in 10th degrees
+ if(0.0 != fRotate)
+ {
+ // Fit rotated graphic to center of available space, keeping page ratio:
+ // Adapt scaling ratio of unit object and rotate it
+ aRetval.scale(1.0, rTargetRange.getHeight() / rTargetRange.getWidth());
+ aRetval.rotate(fRotate);
+
+ // get the range to see where we are in unit coordinates
+ basegfx::B2DRange aFullRange(0.0, 0.0, 1.0, 1.0);
+ aFullRange.transform(aRetval);
+
+ // detect needed scales in X/Y and choose the smallest for staying inside the
+ // available space while keeping aspect ratio of the source
+ const double fScaleX(rTargetRange.getWidth() / aFullRange.getWidth());
+ const double fScaleY(rTargetRange.getHeight() / aFullRange.getHeight());
+ const double fScaleMin(std::min(fScaleX, fScaleY));
+
+ // TopLeft to zero, then scale, then move to center of available space
+ aRetval.translate(-aFullRange.getMinX(), -aFullRange.getMinY());
+ aRetval.scale(fScaleMin, fScaleMin);
+ aRetval.translate(
+ rTargetRange.getCenterX() - (0.5 * fScaleMin * aFullRange.getWidth()),
+ rTargetRange.getCenterY() - (0.5 * fScaleMin * aFullRange.getHeight()));
+ }
+ else
+ {
+ // just scale/translate needed
+ aRetval *= createScaleTranslateB2DHomMatrix(
+ rTargetRange.getRange(),
+ rTargetRange.getMinimum());
+ }
+
+ return aRetval;
+ }
+
/// special for the case to map from source range to target range
B2DHomMatrix createSourceRangeTargetRangeTransform(
const B2DRange& rSourceRange,
diff --git a/include/basegfx/matrix/b2dhommatrixtools.hxx b/include/basegfx/matrix/b2dhommatrixtools.hxx
index c60a6ac96c21..e462bad54b8e 100644
--- a/include/basegfx/matrix/b2dhommatrixtools.hxx
+++ b/include/basegfx/matrix/b2dhommatrixtools.hxx
@@ -126,6 +126,13 @@ namespace basegfx
fRadiant);
}
+ /// special for creating a mapping for a Range rotated around it's center
+ /// while keeping AspectRatio unchanged and staying inside the given Range
+ /// by optimally using the available space (no overlap or outside allowed)
+ BASEGFX_DLLPUBLIC B2DHomMatrix createRotateAroundCenterKeepAspectRatioStayInsideRange(
+ const basegfx::B2DRange& rTargetRange,
+ double fRotate);
+
/// special for the case to map from source range to target range
BASEGFX_DLLPUBLIC B2DHomMatrix createSourceRangeTargetRangeTransform(
const B2DRange& rSourceRange,
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index aed40a9f13d1..90a6ad41f452 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -3585,200 +3585,62 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
{
Hide();
- if( DragStat().GetDX()==0 && DragStat().GetDY()==0 )
+ if(0 == DragStat().GetDX() && 0 == DragStat().GetDY())
+ {
+ // no change, done
return false;
+ }
const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
- if( rMarkList.GetMarkCount() != 1 )
+ if(1 != rMarkList.GetMarkCount())
+ {
+ // Crop only with single Object selected
return false;
+ }
- SdrObject* pSdrObject = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
-
- // tdf#34555: in order to implement visual crop in Writer, we need to handle two
- // cases:
- // EndSdrDrag when called in Impress/Draw/...: pSdrObject is a SdrGrafObj
- // EndSdrDrag when called in Writer: pSdrObject is a SwVirtFlyDrawObj
- // Main principle: if marked object is not SdrGrafObj, we start a generic handling
- // based on virtual methods added to SdrObject, on MM100/Twip coordinates and so on.
- // If marked object is SdrGrafObj, we do all the work here with matrix based
- // coordinates.
- if (dynamic_cast<const SdrGrafObj*>( pSdrObject) == nullptr) {
- const bool bUndo = getSdrDragView().IsUndoEnabled();
- if( bUndo )
- {
- OUString aUndoStr;
- ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr);
- getSdrDragView().BegUndo( aUndoStr );
- getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoGeoObject(*pSdrObject));
- // also need attr undo, the SdrGrafCropItem will be changed
- getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pSdrObject));
- }
-
- // We need to produce a reference point and two (X & Y) scales
- SdrHdl* pRef1=GetHdlList().GetHdl(SdrHdlKind::UpperLeft);
- SdrHdl* pRef2=GetHdlList().GetHdl(SdrHdlKind::LowerRight);
-
- if (pRef1==nullptr || pRef2==nullptr)
- return false;
-
- tools::Rectangle rect(pRef1->GetPos(),pRef2->GetPos());
-
- Point aEnd(DragStat().GetNow());
- Point aStart(DragStat().GetStart());
- Point aRef(rect.Center());
-
- // Reference point is the point opposed to the dragged handle
- switch(GetDragHdlKind())
- {
- case SdrHdlKind::UpperLeft: aRef = rect.BottomRight(); break;
- case SdrHdlKind::Upper: aRef = rect.BottomCenter(); DragStat().SetHorFixed(true); break;
- case SdrHdlKind::UpperRight: aRef = rect.BottomLeft(); break;
- case SdrHdlKind::Left : aRef = rect.RightCenter(); DragStat().SetVerFixed(true); break;
- case SdrHdlKind::Right: aRef = rect.LeftCenter(); DragStat().SetVerFixed(true); break;
- case SdrHdlKind::LowerLeft: aRef = rect.TopRight(); break;
- case SdrHdlKind::Lower: aRef = rect.TopCenter(); DragStat().SetHorFixed(true); break;
- case SdrHdlKind::LowerRight: aRef = rect.TopLeft(); break;
- default: break;
- }
-
- // By default, scale is new size / old size
- long nXDiv = aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1;
- long nYDiv = aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1;
- long nXMul = aEnd.X()-aRef.X();
- long nYMul = aEnd.Y()-aRef.Y();
-
- if (nXDiv<0)
- {
- nXDiv=-nXDiv;
- nXMul=-nXMul;
- }
-
- if (nYDiv<0)
- {
- nYDiv=-nYDiv;
- nYMul=-nYMul;
- }
-
- // Take ortho into account.
- bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul;
- bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul;
- bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed();
-
- if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
- {
- if (std::abs(nXDiv)<=1 || std::abs(nYDiv)<=1)
- bOrtho=false;
-
- if (bOrtho)
- {
- if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho())
- {
- nXMul=nYMul;
- nXDiv=nYDiv;
- }
- else
- {
- nYMul=nXMul;
- nYDiv=nXDiv;
- }
- }
- }
- else
- {
- if (bOrtho)
- {
- if (DragStat().IsHorFixed())
- {
- bXNeg=false;
- nXMul=nYMul;
- nXDiv=nYDiv;
- }
-
- if (DragStat().IsVerFixed())
- {
- bYNeg=false;
- nYMul=nXMul;
- nYDiv=nXDiv;
- }
- }
- else
- {
- if (DragStat().IsHorFixed())
- {
- bXNeg=false;
- nXMul=1;
- nXDiv=1;
- }
+ // prepare for SdrGrafObj or others. This code has to work with usual
+ // SdrGrafObj's from Draw/Impress/Calc, but also with SdrObjects from
+ // Writer. It would be better to handle this in Writer directly, but
+ // there are currently no easy mechanisms to plug an alternative interaction
+ // from there
+ SdrObject* pSdrObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ struct SdrObjDeleter { void operator()(SdrObject* b) { SdrObject::Free(b); }};
+ std::unique_ptr< SdrObject, SdrObjDeleter > pFullDragClone;
+ bool bExternal(false);
+ SdrObject* pExternalSdrObject(nullptr);
- if (DragStat().IsVerFixed())
- {
- bYNeg=false;
- nYMul=1;
- nYDiv=1;
- }
- }
- }
- Fraction aXFact(nXMul,nXDiv);
- Fraction aYFact(nYMul,nYDiv);
- Fraction aMaxFact(0x7FFFFFFF,1);
+ // RotGrfFlyFrame: Crop decision for DrawingLayer/Writer now
+ // locally, no two-in-one methods any more
+ if (nullptr != pSdrObject && dynamic_cast< const SdrGrafObj* >(pSdrObject) == nullptr)
+ {
+ // If Writer, get the already offered for interaction SdrGrafObj
+ // and set up for using that replacement object that contains the
+ // real transformation. That SdrObject is owned and has to be deleted,
+ // so use a std::unique_ptr with special handling for the protected
+ // SDrObject destructor
+ pFullDragClone.reset(pSdrObject->getFullDragClone());
- if (bOrtho)
+ if(pFullDragClone && dynamic_cast< SdrGrafObj* >(pFullDragClone.get()))
{
- if (aXFact>aMaxFact)
- {
- aXFact=aMaxFact;
- aYFact=aMaxFact;
- }
-
- if (aYFact>aMaxFact)
- {
- aXFact=aMaxFact;
- aYFact=aMaxFact;
- }
+ bExternal = true;
+ pExternalSdrObject = pSdrObject;
+ pSdrObject = pFullDragClone.get();
}
-
- if (bXNeg)
- aXFact=Fraction(-aXFact.GetNumerator(),aXFact.GetDenominator());
-
- if (bYNeg)
- aYFact=Fraction(-aYFact.GetNumerator(),aYFact.GetDenominator());
-
- // With Ref point (opposed to dragged point), X scale and Y scale,
- // we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
- // crop
- pSdrObject->Crop(aRef, aXFact, aYFact);
-
- if( bUndo )
- getSdrDragView().EndUndo();
-
- // Job's done
- return true;
}
- // This part of code handles the case where pSdrObject is SdrGrafObj
-
+ // get and check for SdrGrafObj now
SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( pSdrObject );
- if( !pObj || (pObj->GetGraphicType() == GraphicType::NONE) || (pObj->GetGraphicType() == GraphicType::Default) )
- return false;
- const GraphicObject& rGraphicObject = pObj->GetGraphicObject();
- const MapMode aMapMode100thmm(MapUnit::Map100thMM);
- Size aGraphicSize(rGraphicObject.GetPrefSize());
-
- if( MapUnit::MapPixel == rGraphicObject.GetPrefMapMode().GetMapUnit() )
- aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm );
- else
- aGraphicSize = OutputDevice::LogicToLogic( aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
-
- if( aGraphicSize.Width() == 0 || aGraphicSize.Height() == 0 )
+ if(!pObj)
+ {
return false;
+ }
- const SdrGrafCropItem& rOldCrop = static_cast<const SdrGrafCropItem&>(pObj->GetMergedItem(SDRATTR_GRAFCROP));
-
- const bool bUndo = getSdrDragView().IsUndoEnabled();
+ // no undo for external needed, done there
+ const bool bUndo(!bExternal && getSdrDragView().IsUndoEnabled());
- if( bUndo )
+ if(bUndo)
{
OUString aUndoStr;
ImpTakeDescriptionStr(STR_DragMethCrop, aUndoStr);
@@ -3789,20 +3651,15 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
getSdrDragView().AddUndo( getSdrDragView().GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj));
}
- // new part to commute the user's drag activities
// get the original objects transformation
basegfx::B2DHomMatrix aOriginalMatrix;
basegfx::B2DPolyPolygon aPolyPolygon;
bool bShearCorrected(false);
-
- // get transformation from object
pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon);
{ // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
- basegfx::B2DTuple aScale;
- basegfx::B2DTuple aTranslate;
+ basegfx::B2DTuple aScale, aTranslate;
double fRotate(0.0), fShearX(0.0);
-
aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
if(!basegfx::fTools::equalZero(fShearX))
@@ -3816,11 +3673,6 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
}
}
- // invert it to be able to work on unit coordinates
- basegfx::B2DHomMatrix aInverse(aOriginalMatrix);
-
- aInverse.invert();
-
// generate start point of original drag vector in unit coordinates (the
// vis-a-vis of the drag point)
basegfx::B2DPoint aLocalStart(0.0, 0.0);
@@ -3839,7 +3691,10 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
default: break;
}
- // create the current drag position in unit coordinates
+ // create the current drag position in unit coordinates. To get there,
+ // transform back the DragPoint to UnitCoordinates
+ basegfx::B2DHomMatrix aInverse(aOriginalMatrix);
+ aInverse.invert();
basegfx::B2DPoint aLocalCurrent(aInverse * basegfx::B2DPoint(DragStat().GetNow().X(), DragStat().GetNow().Y()));
// if one of the edge handles is used, limit to X or Y drag only
@@ -3884,48 +3739,18 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
}
}
- // preparematrix to apply to object; evtl. back-correct shear
- basegfx::B2DHomMatrix aNewObjectMatrix(aOriginalMatrix * aDiscreteChangeMatrix);
-
- if(bShearCorrected)
- {
- // back-correct shear
- basegfx::B2DTuple aScale;
- basegfx::B2DTuple aTranslate;
- double fRotate(0.0), fShearX(0.0);
-
- aNewObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
- aNewObjectMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale,
- -fShearX,
- fRotate,
- aTranslate);
- }
-
- // apply change to object by applying the unit coordinate change followed
- // by the original change
- pObj->TRSetBaseGeometry(aNewObjectMatrix, aPolyPolygon);
-
- // the following old code uses aOldRect/aNewRect to calculate the crop change for
- // the crop item. It implies unrotated objects, so create the unrotated original
- // rectangle and the unrotated modified rectangle. Latter can in case of shear and/or
- // rotation not be fetched by using
-
- //Rectangle aNewRect( pObj->GetLogicRect() );
-
- // as it was done before because the top-left of that new rect *will* have an offset
- // caused by the evtl. existing shear and/or rotation, so calculate a unrotated
- // rectangle how it would be as a result when applying the unit coordinate change
- // to the unrotated original transformation.
- basegfx::B2DTuple aScale;
- basegfx::B2DTuple aTranslate;
+ // We now have the whole executed Crop in UnitCoordinates in
+ // aDiscreteChangeMatrix, go to concrete sizes now.
+ // Create the unrotated original rectangle and the unrotated modified
+ // rectangle as Ranges
+ basegfx::B2DTuple aScale, aTranslate;
double fRotate, fShearX;
// get access to scale and translate
aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
// prepare unsheared/unrotated versions of the old and new transformation
- const basegfx::B2DHomMatrix aMatrixOriginalNoShearNoRotate(
+ const basegfx::B2DHomMatrix aOriginalMatrixNoShearNoRotate(
basegfx::utils::createScaleTranslateB2DHomMatrix(
basegfx::absolute(aScale),
aTranslate));
@@ -3933,55 +3758,129 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
// create the ranges for these
basegfx::B2DRange aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
basegfx::B2DRange aRangeNewNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
+ aRangeOriginalNoShearNoRotate.transform(aOriginalMatrixNoShearNoRotate);
+ aRangeNewNoShearNoRotate.transform(aOriginalMatrixNoShearNoRotate * aDiscreteChangeMatrix);
+
+ if(bExternal)
+ {
+ // With Ref point (opposed to dragged point), X scale and Y scale,
+ // we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
+ // crop. aRef needs to be adapted to concrete Object's boundaries which
+ // is different from Crop-Ranges. This is because the Graphic and it's
+ // SdrObject representaion is inside the FlyFrame, but not identical
+ // with it.
+ const tools::Rectangle& rOutRect(pExternalSdrObject->GetCurrentBoundRect());
+ const basegfx::B2DHomMatrix aExternalTransform(
+ basegfx::utils::createScaleTranslateB2DHomMatrix(
+ rOutRect.getWidth(), rOutRect.getHeight(),
+ rOutRect.Left(), rOutRect.Top()));
+ const basegfx::B2DPoint aRef(aExternalTransform * aLocalStart);
+ const double fScaleX(aRangeNewNoShearNoRotate.getWidth() / aRangeOriginalNoShearNoRotate.getWidth());
+ const double fScaleY(aRangeNewNoShearNoRotate.getHeight() / aRangeOriginalNoShearNoRotate.getHeight());
+
+ pExternalSdrObject->Crop(
+ Point(basegfx::fround(aRef.getX()), basegfx::fround(aRef.getY())),
+ Fraction(fScaleX),
+ Fraction(fScaleY));
+ }
+ else
+ {
+ // prepare matrix to apply to object; evtl. back-correct shear
+ basegfx::B2DHomMatrix aNewObjectMatrix(aOriginalMatrix * aDiscreteChangeMatrix);
+
+ if(bShearCorrected)
+ {
+ // back-correct shear
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate(0.0), fShearX(0.0);
- aRangeOriginalNoShearNoRotate.transform(aMatrixOriginalNoShearNoRotate);
- aRangeNewNoShearNoRotate.transform(aMatrixOriginalNoShearNoRotate * aDiscreteChangeMatrix);
-
- // extract the old Rectangle structures
- tools::Rectangle aOldRect(
- basegfx::fround(aRangeOriginalNoShearNoRotate.getMinX()),
- basegfx::fround(aRangeOriginalNoShearNoRotate.getMinY()),
- basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxX()),
- basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxY()));
- tools::Rectangle aNewRect(
- basegfx::fround(aRangeNewNoShearNoRotate.getMinX()),
- basegfx::fround(aRangeNewNoShearNoRotate.getMinY()),
- basegfx::fround(aRangeNewNoShearNoRotate.getMaxX()),
- basegfx::fround(aRangeNewNoShearNoRotate.getMaxY()));
-
- // continue with the old original stuff
- if (!aOldRect.GetWidth() || !aOldRect.GetHeight())
- throw o3tl::divide_by_zero();
-
- double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth();
- double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight();
-
- sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left();
- sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top();
- sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right();
- sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom();
-
- if(pObj->IsMirrored())
- {
- // mirrored X or Y, for old stuff, exchange X
- // check for aw080
- sal_Int32 nTmp(nDiffLeft);
- nDiffLeft = -nDiffRight;
- nDiffRight = -nTmp;
- }
-
- sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
- sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
- sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
- sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
-
- SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool();
- SfxItemSet aSet( rPool, svl::Items<SDRATTR_GRAFCROP, SDRATTR_GRAFCROP>{} );
- aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
- getSdrDragView().SetAttributes( aSet, false );
-
- if( bUndo )
+ aNewObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ aNewObjectMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+ aScale,
+ -fShearX,
+ fRotate,
+ aTranslate);
+ }
+
+ // apply change to object by applying the unit coordinate change followed
+ // by the original change
+ pObj->TRSetBaseGeometry(aNewObjectMatrix, aPolyPolygon);
+
+ // extract the old Rectangle structures
+ tools::Rectangle aOldRect(
+ basegfx::fround(aRangeOriginalNoShearNoRotate.getMinX()),
+ basegfx::fround(aRangeOriginalNoShearNoRotate.getMinY()),
+ basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxX()),
+ basegfx::fround(aRangeOriginalNoShearNoRotate.getMaxY()));
+ tools::Rectangle aNewRect(
+ basegfx::fround(aRangeNewNoShearNoRotate.getMinX()),
+ basegfx::fround(aRangeNewNoShearNoRotate.getMinY()),
+ basegfx::fround(aRangeNewNoShearNoRotate.getMaxX()),
+ basegfx::fround(aRangeNewNoShearNoRotate.getMaxY()));
+
+ // continue with the old original stuff
+ if (!aOldRect.GetWidth() || !aOldRect.GetHeight())
+ {
+ throw o3tl::divide_by_zero();
+ }
+
+ if((pObj->GetGraphicType() == GraphicType::NONE) || (pObj->GetGraphicType() == GraphicType::Default))
+ {
+ return false;
+ }
+
+ const GraphicObject& rGraphicObject = pObj->GetGraphicObject();
+ const MapMode aMapMode100thmm(MapUnit::Map100thMM);
+ Size aGraphicSize(rGraphicObject.GetPrefSize());
+
+ if(MapUnit::MapPixel == rGraphicObject.GetPrefMapMode().GetMapUnit())
+ {
+ aGraphicSize = Application::GetDefaultDevice()->PixelToLogic(aGraphicSize, aMapMode100thmm);
+ }
+ else
+ {
+ aGraphicSize = OutputDevice::LogicToLogic(aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
+ }
+
+ if(0 == aGraphicSize.Width() || 0 == aGraphicSize.Height())
+ {
+ return false;
+ }
+
+ const SdrGrafCropItem& rOldCrop = static_cast<const SdrGrafCropItem&>(pObj->GetMergedItem(SDRATTR_GRAFCROP));
+ double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / (double)aOldRect.GetWidth();
+ double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / (double)aOldRect.GetHeight();
+
+ sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left();
+ sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top();
+ sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right();
+ sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom();
+
+ if(pObj->IsMirrored())
+ {
+ // mirrored X or Y, for old stuff, exchange X
+ // check for aw080
+ sal_Int32 nTmp(nDiffLeft);
+ nDiffLeft = -nDiffRight;
+ nDiffRight = -nTmp;
+ }
+
+ sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
+ sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
+ sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
+ sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
+
+ SfxItemPool& rPool = getSdrDragView().GetModel()->GetItemPool();
+ SfxItemSet aSet( rPool, svl::Items<SDRATTR_GRAFCROP, SDRATTR_GRAFCROP>{} );
+ aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
+ getSdrDragView().SetAttributes( aSet, false );
+ }
+
+ if(bUndo)
+ {
getSdrDragView().EndUndo();
+ }
return true;
}
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 42eac79c45ee..6a23088246c4 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -757,53 +757,24 @@ bool paintUsingPrimitivesHelper(
return false;
}
-void paintGraphicUsingPrimitivesHelper(vcl::RenderContext & rOutputDevice,
- GraphicObject const& rGrfObj, GraphicAttr const& rGraphicAttr,
- SwRect const& rAlignedGrfArea)
+void paintGraphicUsingPrimitivesHelper(
+ vcl::RenderContext & rOutputDevice,
+ GraphicObject const& rGrfObj,
+ GraphicAttr const& rGraphicAttr,
+ SwRect const& rAlignedGrfArea)
{
- // unify using GraphicPrimitive2D
+ // RotGrfFlyFrame: unify using GraphicPrimitive2D
// -> the primitive handles all crop and mirror stuff
// -> the primitive renderer will create the needed pdf export data
// -> if bitmap content, it will be cached system-dependent
const basegfx::B2DRange aTargetRange(
rAlignedGrfArea.Left(), rAlignedGrfArea.Top(),
rAlignedGrfArea.Right(), rAlignedGrfArea.Bottom());
- basegfx::B2DHomMatrix aTargetTransform;
-
- // RotGrfFlyFrame: Take rotation into account. Rotation is in 10th degrees
- if(0 != rGraphicAttr.GetRotation())
- {
- // Fit rotated graphic to center of available space, keeping page ratio:
- // Adapt scaling ratio of unit object and rotate it
- const double fRotate(static_cast< double >(-rGraphicAttr.GetRotation()) * (M_PI/1800.0));
- aTargetTransform.scale(1.0, aTargetRange.getHeight() / aTargetRange.getWidth());
- aTargetTransform.rotate(fRotate);
-
- // get the range to see where we are in unit coordinates
- basegfx::B2DRange aFullRange(0.0, 0.0, 1.0, 1.0);
- aFullRange.transform(aTargetTransform);
-
- // detect needed scales in X/Y and choose the smallest for staying inside the
- // available space while keeping aspect ratio of the source
- const double fScaleX(aTargetRange.getWidth() / aFullRange.getWidth());
- const double fScaleY(aTargetRange.getHeight() / aFullRange.getHeight());
- const double fScaleMin(std::min(fScaleX, fScaleY));
-
- // TopLeft to zero, then scale, then move to center of available space
- aTargetTransform.translate(-aFullRange.getMinX(), -aFullRange.getMinY());
- aTargetTransform.scale(fScaleMin, fScaleMin);
- aTargetTransform.translate(
- aTargetRange.getCenterX() - (0.5 * fScaleMin * aFullRange.getWidth()),
- aTargetRange.getCenterY() - (0.5 * fScaleMin * aFullRange.getHeight()));
- }
- else
- {
- // just scale/translate needed
- aTargetTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(
- aTargetRange.getRange(),
- aTargetRange.getMinimum());
- }
-
+ const double fRotate(static_cast< double >(-rGraphicAttr.GetRotation()) * (M_PI/1800.0));
+ const basegfx::B2DHomMatrix aTargetTransform(
+ basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
+ aTargetRange,
+ fRotate));
drawinglayer::primitive2d::Primitive2DContainer aContent(1);
bool bDone(false);
diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
index 0696af0e59d1..358085bd2760 100644
--- a/sw/source/core/draw/dflyobj.cxx
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -59,6 +59,8 @@
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <sw_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <notxtfrm.hxx>
using namespace ::com::sun::star;
@@ -920,20 +922,96 @@ void SwVirtFlyDrawObj::Crop(const Point& rRef, const Fraction& xFact, const Frac
GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
}
-void SwVirtFlyDrawObj::addCropHandles(SdrHdlList& rTarget) const
+// RotGrfFlyFrame: Helper to access possible rotation of Graphic contained in FlyFrame
+sal_uInt16 SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame() const
{
- tools::Rectangle aRect(GetSnapRect());
+ sal_uInt16 nRetval(0);
+ const SwNoTextFrame* pNoTx = dynamic_cast< const SwNoTextFrame* >(GetFlyFrame()->Lower());
- if(!aRect.IsEmpty())
+ if(pNoTx)
{
- rTarget.AddHdl(new SdrCropHdl(aRect.TopLeft() , SdrHdlKind::UpperLeft, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.TopCenter() , SdrHdlKind::Upper, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.TopRight() , SdrHdlKind::UpperRight, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.LeftCenter() , SdrHdlKind::Left , 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.RightCenter() , SdrHdlKind::Right, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.BottomLeft() , SdrHdlKind::LowerLeft, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.BottomCenter(), SdrHdlKind::Lower, 0, 0));
- rTarget.AddHdl(new SdrCropHdl(aRect.BottomRight() , SdrHdlKind::LowerRight, 0, 0));
+ SwNoTextNode& rNoTNd = const_cast< SwNoTextNode& >(*static_cast<const SwNoTextNode*>(pNoTx->GetNode()));
+ SwGrfNode* pGrfNd = rNoTNd.GetGrfNode();
+
+ if(nullptr != pGrfNd)
+ {
+ const SwAttrSet& rSet = pGrfNd->GetSwAttrSet();
+ const SwRotationGrf& rRotation = rSet.GetRotationGrf();
+
+ nRetval = rRotation.GetValue();
+ }
+ }
+
+ return nRetval;
+}
+
+SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
+{
+ // call parent
+ SdrObject* pRetval = SdrVirtObj::getFullDragClone();
+
+ if(pRetval)
+ {
+ // 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 aOutRect(GetFlyFrame()->Frame().SVRect());
+ const basegfx::B2DRange aTargetRange(
+ aOutRect.Left(), aOutRect.Top(),
+ aOutRect.Right(), aOutRect.Bottom());
+ const basegfx::B2DHomMatrix aTargetTransform(
+ basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
+ aTargetRange,
+ fRotate));
+
+ pRetval->TRSetBaseGeometry(aTargetTransform, basegfx::B2DPolyPolygon());
+ }
+ }
+
+ return pRetval;
+}
+
+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());
+
+ if(!aTargetRange.isEmpty())
+ {
+ const sal_uInt16 nRotation(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame());
+ const double fRotate(static_cast< double >(-nRotation) * (M_PI/1800.0));
+ const basegfx::B2DHomMatrix aTargetTransform(
+ basegfx::utils::createRotateAroundCenterKeepAspectRatioStayInsideRange(
+ aTargetRange,
+ fRotate));
+ basegfx::B2DPoint aPos;
+ const double fShearX(0.0);
+
+ aPos = aTargetTransform * basegfx::B2DPoint(0.0, 0.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperLeft, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(0.5, 0.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Upper, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(1.0, 0.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::UpperRight, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(0.0, 0.5);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Left , fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(1.0, 0.5);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Right, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(0.0, 1.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerLeft, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(0.5, 1.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::Lower, fShearX, fRotate));
+ aPos = aTargetTransform * basegfx::B2DPoint(1.0, 1.0);
+ rTarget.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos.getX()), basegfx::fround(aPos.getY())), SdrHdlKind::LowerRight, fShearX, fRotate));
+ }
}
}
diff --git a/sw/source/core/inc/dflyobj.hxx b/sw/source/core/inc/dflyobj.hxx
index 9368eb893b07..528edc8aff39 100644
--- a/sw/source/core/inc/dflyobj.hxx
+++ b/sw/source/core/inc/dflyobj.hxx
@@ -58,6 +58,10 @@ class SwVirtFlyDrawObj : public SdrVirtObj
private:
SwFlyFrame *m_pFlyFrame;
+ // RotGrfFlyFrame: Helper to acces sthe rotation angle (in 10th degrees, left-handed)
+ // of a GraphicFrame
+ sal_uInt16 getPossibleRotationFromFraphicFrame() const;
+
protected:
// AW: Need own sdr::contact::ViewContact since AnchorPos from parent is
// not used but something own (top left of new SnapRect minus top left
@@ -102,6 +106,9 @@ public:
virtual void Crop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) override;
virtual void addCropHandles(SdrHdlList& rTarget) const override;
+ // FullDrag support
+ virtual SdrObject* getFullDragClone() const override;
+
const SwFrameFormat *GetFormat() const;
SwFrameFormat *GetFormat();
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index 305c8ffb5495..f0351fa6de29 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -72,10 +72,11 @@ bool DrawFillAttributes(
const basegfx::utils::B2DClipState& rClipState,
OutputDevice& rOut);
+// RotGrfFlyFrame: Adapted to rotation
void paintGraphicUsingPrimitivesHelper(
- OutputDevice & rOutputDevice,
- GraphicObject const& rGraphicObj, GraphicAttr const& rGraphicAttr,
- SwRect const& rAlignedGrfArea);
+ OutputDevice & rOutputDevice,
+ GraphicObject const& rGraphicObj, GraphicAttr const& rGraphicAttr,
+ SwRect const& rAlignedGrfArea);
// method to align rectangle.
// Created declaration here to avoid <extern> declarations
commit 4ddd74e2d119eb7b25df75a65fcb214ce08ec672
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Tue Sep 26 15:41:23 2017 +0200
RotGrfFlyFrame: Minimal working rotation solution
This version allows rotation (in 10th degrees) and perserves
it over save/load cycles. Rotation of multiples of 90 degree
behave close to original except not changing the contained
Graphic and being adaptable to all kinds of graphic. The
rotated Graphic is displayed centered and under preserved
AspectRatio in the available frame space (so no rotation,
180 degree is identical, 90/-90 is identical with 1:1 ratio
of the graphic)
Change-Id: I54b3385f709ee0d34a55324aca919dcd2ce0c009
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index a35f679d10be..42eac79c45ee 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -773,16 +773,36 @@ void paintGraphicUsingPrimitivesHelper(vcl::RenderContext & rOutputDevice,
// RotGrfFlyFrame: Take rotation into account. Rotation is in 10th degrees
if(0 != rGraphicAttr.GetRotation())
{
+ // Fit rotated graphic to center of available space, keeping page ratio:
+ // Adapt scaling ratio of unit object and rotate it
const double fRotate(static_cast< double >(-rGraphicAttr.GetRotation()) * (M_PI/1800.0));
- aTargetTransform.translate(-0.5, -0.5);
+ aTargetTransform.scale(1.0, aTargetRange.getHeight() / aTargetRange.getWidth());
aTargetTransform.rotate(fRotate);
- aTargetTransform.translate(0.5, 0.5);
- }
- // needed scale/translate
- aTargetTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(
- aTargetRange.getRange(),
- aTargetRange.getMinimum());
+ // get the range to see where we are in unit coordinates
+ basegfx::B2DRange aFullRange(0.0, 0.0, 1.0, 1.0);
+ aFullRange.transform(aTargetTransform);
+
+ // detect needed scales in X/Y and choose the smallest for staying inside the
+ // available space while keeping aspect ratio of the source
+ const double fScaleX(aTargetRange.getWidth() / aFullRange.getWidth());
+ const double fScaleY(aTargetRange.getHeight() / aFullRange.getHeight());
+ const double fScaleMin(std::min(fScaleX, fScaleY));
+
+ // TopLeft to zero, then scale, then move to center of available space
+ aTargetTransform.translate(-aFullRange.getMinX(), -aFullRange.getMinY());
+ aTargetTransform.scale(fScaleMin, fScaleMin);
+ aTargetTransform.translate(
+ aTargetRange.getCenterX() - (0.5 * fScaleMin * aFullRange.getWidth()),
+ aTargetRange.getCenterY() - (0.5 * fScaleMin * aFullRange.getHeight()));
+ }
+ else
+ {
+ // just scale/translate needed
+ aTargetTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aTargetRange.getRange(),
+ aTargetRange.getMinimum());
+ }
drawinglayer::primitive2d::Primitive2DContainer aContent(1);
bool bDone(false);
diff --git a/sw/source/uibase/frmdlg/frmmgr.cxx b/sw/source/uibase/frmdlg/frmmgr.cxx
index fdc883b6a22a..c73238be62ea 100644
--- a/sw/source/uibase/frmdlg/frmmgr.cxx
+++ b/sw/source/uibase/frmdlg/frmmgr.cxx
@@ -46,10 +46,15 @@
using namespace ::com::sun::star;
static sal_uInt16 aFrameMgrRange[] = {
- RES_FRMATR_BEGIN, RES_FRMATR_END-1,
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1, // 87-129
+
+ // RotGrfFlyFrame: Support here, but seems not to be
+ // added in range of m_pOwnSh->GetFlyFrameAttr result
+ // (see below). Tried to find, but could not identify
+ RES_GRFATR_ROTATION, RES_GRFATR_ROTATION, // 132
// FillAttribute support
- XATTR_FILL_FIRST, XATTR_FILL_LAST,
+ XATTR_FILL_FIRST, XATTR_FILL_LAST, // 1014-1033
SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
FN_SET_FRM_NAME, FN_SET_FRM_NAME,
@@ -569,13 +574,17 @@ void SwFlyFrameAttrMgr::SetHeightSizeType( SwFrameSize eType )
m_aSet.Put( aSize );
}
-void SwFlyFrameAttrMgr::SetRotation(sal_uInt32 nOld, sal_uInt32 nNew, Size aUnrotatedSize)
+void SwFlyFrameAttrMgr::SetRotation(sal_uInt16 nOld, sal_uInt16 nNew, const Size& rUnrotatedSize)
{
- // RotGrfFlyFrame: Central handling of real change of rotation here. Adaption of pos/size
- // may be wanted in the future
+ // 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
+ // 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
+ // 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)
{
- m_pOwnSh->SetAttrItem(SwRotationGrf(static_cast<sal_uInt16>(nNew), aUnrotatedSize));
+ m_pOwnSh->SetAttrItem(SwRotationGrf(nNew, rUnrotatedSize));
}
}
diff --git a/sw/source/uibase/inc/frmmgr.hxx b/sw/source/uibase/inc/frmmgr.hxx
index cdc3680ab894..e0f939ff2223 100644
--- a/sw/source/uibase/inc/frmmgr.hxx
+++ b/sw/source/uibase/inc/frmmgr.hxx
@@ -93,7 +93,7 @@ public:
void SetHeightSizeType(SwFrameSize eType);
// rotation
- void SetRotation(sal_uInt32 nOld, sal_uInt32 nNew, Size aUnrotatedSize);
+ void SetRotation(sal_uInt16 nOld, sal_uInt16 nNew, const Size& rUnrotatedSize);
// space to content
void SetLRSpace( long nLeft,
diff --git a/sw/source/uibase/shells/grfsh.cxx b/sw/source/uibase/shells/grfsh.cxx
index 7b2e034ae670..0914846b7857 100644
--- a/sw/source/uibase/shells/grfsh.cxx
+++ b/sw/source/uibase/shells/grfsh.cxx
@@ -893,12 +893,6 @@ void SwGrfShell::GetAttrState(SfxItemSet &rSet)
void SwGrfShell::ExecuteRotation(SfxRequest const &rReq)
{
// RotGrfFlyFrame: Modify rotation attribute instead of manipulating the graphic
- SwWrtShell& rShell = GetShell();
- SfxItemSet aSet( rShell.GetAttrPool(), svl::Items<
- RES_GRFATR_ROTATION, RES_GRFATR_ROTATION,
- SID_ATTR_TRANSFORM_ANGLE, SID_ATTR_TRANSFORM_ANGLE>{} );
- rShell.GetCurAttr( aSet );
- const SwRotationGrf& rRotation = static_cast<const SwRotationGrf&>(aSet.Get(RES_GRFATR_ROTATION));
sal_uInt16 aRotation(0);
if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_LEFT)
@@ -916,22 +910,23 @@ void SwGrfShell::ExecuteRotation(SfxRequest const &rReq)
if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RESET || 0 != aRotation)
{
- rShell.StartAllAction();
- rShell.StartUndo(SwUndoId::START);
+ SwWrtShell& rShell = GetShell();
+ SfxItemSet aSet( rShell.GetAttrPool(), svl::Items<RES_GRFATR_ROTATION, RES_GRFATR_ROTATION>{} );
+ rShell.GetCurAttr( aSet );
+ const SwRotationGrf& rRotation = static_cast<const SwRotationGrf&>(aSet.Get(RES_GRFATR_ROTATION));
+ SwFlyFrameAttrMgr aMgr(false, &rShell, rShell.IsFrameSelected() ? Frmmgr_Type::NONE : Frmmgr_Type::GRF);
+ // RotGrfFlyFrame: Possible rotation change here, SwFlyFrameAttrMgr aMgr is available
if (rReq.GetSlot() == SID_ROTATE_GRAPHIC_RESET)
{
- rShell.SetAttrItem(SwRotationGrf(0, rRotation.GetUnrotatedSize()));
+ aMgr.SetRotation(rRotation.GetValue(), 0, rRotation.GetUnrotatedSize());
}
else if(0 != aRotation)
{
- sal_uInt16 aNewRotation((aRotation + rRotation.GetValue()) % 3600);
+ const sal_uInt16 aNewRotation((aRotation + rRotation.GetValue()) % 3600);
- rShell.SetAttrItem(SwRotationGrf(aNewRotation, rRotation.GetUnrotatedSize()));
+ aMgr.SetRotation(rRotation.GetValue(), aNewRotation, rRotation.GetUnrotatedSize());
}
-
- rShell.EndUndo(SwUndoId::END);
- rShell.EndAllAction();
}
}
commit a42b0985c7619efdc934bb1cf19e5e2c2b6faea2
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Fri Sep 22 15:28:33 2017 +0200
RotGrfFlyFrame: Initial adaptions
To allow free rotation of Graphic FlyFrames in Writer,
several adaptions are necessary. This change takes care
of all needed changes to internally support a freely
definable rotation angle for that case. Save/Load round
trip is working, the graphic does no longer get modified
and added in 90-degree-changed state to the object, the
original will be preserved. Support for needed slot in
core/ui is implemented. Rotation can be applied from
Menus/Toolbars in the known 90/180 degree steps. Added
a slot/Button/command to reset rotation in these cases.
Added support in Sidebar to rotate using the rotation
wheel and/or numeric field. These fields and support added
to Image TabPage, too, fully functional.
Missing now is a solution for displaying the rotated
Graphic. For now, it just gets rotated, but this will not
be the final state of this change.
Change-Id: I6f3b85ebb5be2b4ad3311c536d54f27a37a494e7
RotGrfFlyFrame: Linux build adaptions
Change-Id: I365287ecd6525b1972e8436d61332f7121d88649
diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc
index 84103287e776..79ebc50726c1 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 */
// new slots for panels
#define SID_ATTR_FILL_TRANSPARENCE ( SID_SVX_START + 1124 )
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index 5803979d41f8..52fec078a080 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -983,6 +983,14 @@
<value>1</value>
</prop>
</node>
+ <node oor:name=".uno:RotateReset" oor:op="replace">
+ <prop oor:name="Label" oor:type="xs:string">
+ <value xml:lang="en-US">Reset R~otation</value>
+ </prop>
+ <prop oor:name="Properties" oor:type="xs:int">
+ <value>1</value>
+ </prop>
+ </node>
<node oor:name=".uno:NewHtmlDoc" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">Create ~HTML Document</value>
diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi
index 932aef3cb2c2..acd7f4c91f6b 100644
--- a/svx/sdi/svx.sdi
+++ b/svx/sdi/svx.sdi
@@ -4305,6 +4305,23 @@ SfxVoidItem RotateRight SID_ROTATE_GRAPHIC_RIGHT
GroupId = SfxGroupId::Graphic;
]
+SfxVoidItem RotateReset SID_ROTATE_GRAPHIC_RESET
+
+[
+ AutoUpdate = FALSE,
+ FastCall = FALSE,
+ ReadOnlyDoc = TRUE,
+ Toggle = FALSE,
+ Container = FALSE,
+ RecordAbsolute = FALSE,
+ RecordPerSet;
+
+ AccelConfig = TRUE,
+ MenuConfig = TRUE,
+ ToolBoxConfig = TRUE,
+ GroupId = SfxGroupId::Graphic;
+]
+
SfxBoolItem Crop SID_OBJECT_CROP
()
[
diff --git a/svx/source/sidebar/possize/PosSizePropertyPanel.cxx b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
index ab27b80cdc68..3895b2a41208 100644
--- a/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
+++ b/svx/source/sidebar/possize/PosSizePropertyPanel.cxx
@@ -270,6 +270,7 @@ void PosSizePropertyPanel::HandleContextChange(
case CombinedEnumContext(Application::WriterVariants, Context::Graphic):
bShowFlip = true;
+ bShowAngle = true; // RotGrfFlyFrame: Writer FlyFrames for Graphics now support angle
break;
case CombinedEnumContext(Application::Calc, Context::Draw):
diff --git a/sw/sdi/_grfsh.sdi b/sw/sdi/_grfsh.sdi
index 1dc453608103..8291745966bb 100644
--- a/sw/sdi/_grfsh.sdi
+++ b/sw/sdi/_grfsh.sdi
@@ -94,6 +94,20 @@ interface BaseTextGraphic
DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
]
+ SID_ROTATE_GRAPHIC_RESET
+ [
+ ExecMethod = ExecuteRotation ;
+ StateMethod = GetAttrStateForRotation ;
+ DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+ ]
+
+ SID_ATTR_TRANSFORM_ANGLE
+ [
+ ExecMethod = ExecuteRotation ;
+ StateMethod = GetAttrStateForRotation ;
+ DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+ ]
+
SID_OBJECT_CROP
[
ExecMethod = Execute ;
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index c4791e086d4b..a35f679d10be 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -768,10 +768,21 @@ void paintGraphicUsingPrimitivesHelper(vcl::RenderContext & rOutputDevice,
const basegfx::B2DRange aTargetRange(
rAlignedGrfArea.Left(), rAlignedGrfArea.Top(),
rAlignedGrfArea.Right(), rAlignedGrfArea.Bottom());
- const basegfx::B2DHomMatrix aTargetTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- aTargetRange.getRange(),
- aTargetRange.getMinimum()));
+ basegfx::B2DHomMatrix aTargetTransform;
+
+ // RotGrfFlyFrame: Take rotation into account. Rotation is in 10th degrees
+ if(0 != rGraphicAttr.GetRotation())
+ {
+ const double fRotate(static_cast< double >(-rGraphicAttr.GetRotation()) * (M_PI/1800.0));
+ aTargetTransform.translate(-0.5, -0.5);
+ aTargetTransform.rotate(fRotate);
+ aTargetTransform.translate(0.5, 0.5);
+ }
+
+ // needed scale/translate
+ aTargetTransform *= basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aTargetRange.getRange(),
+ aTargetRange.getMinimum());
drawinglayer::primitive2d::Primitive2DContainer aContent(1);
bool bDone(false);
diff --git a/sw/source/ui/frmdlg/frmpage.cxx b/sw/source/ui/frmdlg/frmpage.cxx
index e36595431cee..f1abe60c19fe 100644
--- a/sw/source/ui/frmdlg/frmpage.cxx
+++ b/sw/source/ui/frmdlg/frmpage.cxx
@@ -2388,6 +2388,12 @@ SwGrfExtPage::SwGrfExtPage(vcl::Window *pParent, const SfxItemSet &rSet)
get(m_pBmpWin, "preview");
m_pBmpWin->SetBitmapEx(get<FixedImage>("fallback")->GetImage().GetBitmapEx());
+ // RotGrfFlyFrame: Need Angle and RotateControls now
+ get(m_pFlAngle, "FL_ANGLE");
+ get(m_pNfAngle, "NF_ANGLE");
+ get(m_pCtlAngle, "CTL_ANGLE");
+ m_pCtlAngle->SetLinkedField( m_pNfAngle, 2 );
+
SetExchangeSupport();
m_pMirrorHorzBox->SetClickHdl( LINK(this, SwGrfExtPage, MirrorHdl));
m_pMirrorVertBox->SetClickHdl( LINK(this, SwGrfExtPage, MirrorHdl));
@@ -2411,6 +2417,12 @@ void SwGrfExtPage::dispose()
m_pBmpWin.clear();
m_pConnectED.clear();
m_pBrowseBT.clear();
+
+ // RotGrfFlyFrame: Support RotationAngle
+ m_pFlAngle.clear();
+ m_pNfAngle.clear();
+ m_pCtlAngle.clear();
+
SfxTabPage::dispose();
}
@@ -2432,6 +2444,17 @@ void SwGrfExtPage::Reset(const SfxItemSet *rSet)
m_pConnectED->SetReadOnly(false);
}
+ // RotGrfFlyFrame: Get RotationAngle and set at control
+ if(SfxItemState::SET == rSet->GetItemState( SID_ATTR_TRANSFORM_ANGLE, false, &pItem))
+ {
+ m_pCtlAngle->SetRotation(static_cast<const SfxInt32Item*>(pItem)->GetValue());
+ }
+ else
+ {
+ m_pCtlAngle->SetRotation(0);
+ }
+ m_pCtlAngle->SaveValue();
+
ActivatePage(*rSet);
}
@@ -2559,6 +2582,14 @@ bool SwGrfExtPage::FillItemSet( SfxItemSet *rSet )
rSet->Put( SvxBrushItem( aGrfName, aFilterName, GPOS_LT,
SID_ATTR_GRAF_GRAPHIC ));
}
+
+ // RotGrfFlyFrame: Safe rotation if modified
+ if(m_pCtlAngle->IsValueModified())
+ {
+ rSet->Put(SfxInt32Item(GetWhich(SID_ATTR_TRANSFORM_ANGLE), m_pCtlAngle->GetRotation()));
+ bModified = true;
+ }
+
return bModified;
}
diff --git a/sw/source/uibase/frmdlg/frmmgr.cxx b/sw/source/uibase/frmdlg/frmmgr.cxx
index 73df037c9fdf..fdc883b6a22a 100644
--- a/sw/source/uibase/frmdlg/frmmgr.cxx
+++ b/sw/source/uibase/frmdlg/frmmgr.cxx
@@ -41,6 +41,7 @@
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <com/sun/star/text/RelOrientation.hpp>
+#include <grfatr.hxx>
using namespace ::com::sun::star;
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list