1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <comphelper/lok.hxx>
22 #include <tools/mapunit.hxx>
23 #include <svx/svdtrans.hxx>
24 #include <editeng/protitem.hxx>
25 #include <editeng/opaqitem.hxx>
26 #include <svx/svdpage.hxx>
27 #include <vcl/svapp.hxx>
29 #include <fmtclds.hxx>
30 #include <fmtornt.hxx>
31 #include <fmtfsize.hxx>
34 #include <viewimp.hxx>
38 #include <IDocumentUndoRedo.hxx>
40 #include <dflyobj.hxx>
43 #include <viewopt.hxx>
44 #include <frmtool.hxx>
45 #include <flyfrms.hxx>
46 #include <ndnotxt.hxx>
48 #include <pagefrm.hxx>
49 #include <rootfrm.hxx>
50 #include <textboxhelper.hxx>
55 #include <svx/sdr/properties/defaultproperties.hxx>
56 #include <basegfx/range/b2drange.hxx>
57 #include <basegfx/polygon/b2dpolygontools.hxx>
58 #include <basegfx/polygon/b2dpolygon.hxx>
60 // AW: For VCOfDrawVirtObj and stuff
61 #include <svx/sdr/contact/viewcontactofvirtobj.hxx>
62 #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
63 #include <sw_primitivetypes2d.hxx>
64 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
65 #include <basegfx/matrix/b2dhommatrixtools.hxx>
66 #include <notxtfrm.hxx>
68 using namespace ::com::sun::star
;
70 static bool bInResize
= false;
80 * currently needed since createViewIndependentPrimitive2DSequence() is called when
81 * RecalcBoundRect() is used. There should currently no VOCs being constructed since it
82 * gets not visualized (instead the corresponding SwVirtFlyDrawObj's referencing this one
85 class VCOfSwFlyDrawObj
: public ViewContactOfSdrObj
88 /** This method is responsible for creating the graphical visualisation data
90 * @note ONLY based on model data
92 virtual drawinglayer::primitive2d::Primitive2DContainer
createViewIndependentPrimitive2DSequence() const override
;
95 /// basic constructor, used from SdrObject.
96 explicit VCOfSwFlyDrawObj(SwFlyDrawObj
& rObj
)
97 : ViewContactOfSdrObj(rObj
)
102 drawinglayer::primitive2d::Primitive2DContainer
VCOfSwFlyDrawObj::createViewIndependentPrimitive2DSequence() const
104 // currently gets not visualized, return empty sequence
105 return drawinglayer::primitive2d::Primitive2DContainer();
108 } // end of namespace contact
109 } // end of namespace sdr
111 sdr::properties::BaseProperties
* SwFlyDrawObj::CreateObjectSpecificProperties()
113 // create default properties
114 return new sdr::properties::DefaultProperties(*this);
117 sdr::contact::ViewContact
* SwFlyDrawObj::CreateObjectSpecificViewContact()
119 // needs an own VC since createViewIndependentPrimitive2DSequence()
120 // is called when RecalcBoundRect() is used
121 return new sdr::contact::VCOfSwFlyDrawObj(*this);
124 SwFlyDrawObj::SwFlyDrawObj(SdrModel
& rSdrModel
)
125 : SdrObject(rSdrModel
)
129 SwFlyDrawObj::~SwFlyDrawObj()
133 // SwFlyDrawObj - Factory-Methods
134 SdrInventor
SwFlyDrawObj::GetObjInventor() const
136 return SdrInventor::Swg
;
139 sal_uInt16
SwFlyDrawObj::GetObjIdentifier() const
141 return SwFlyDrawObjIdentifier
;
144 // TODO: Need own primitive to get the FlyFrame paint working
145 namespace drawinglayer
147 namespace primitive2d
149 class SwVirtFlyDrawObjPrimitive
: public BufferedDecompositionPrimitive2D
152 const SwVirtFlyDrawObj
& mrSwVirtFlyDrawObj
;
153 const basegfx::B2DRange maOuterRange
;
156 /// method which is to be used to implement the local decomposition of a 2D primitive
157 virtual void create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& rViewInformation
) const override
;
160 SwVirtFlyDrawObjPrimitive(
161 const SwVirtFlyDrawObj
& rSwVirtFlyDrawObj
,
162 const basegfx::B2DRange
&rOuterRange
)
163 : BufferedDecompositionPrimitive2D(),
164 mrSwVirtFlyDrawObj(rSwVirtFlyDrawObj
),
165 maOuterRange(rOuterRange
)
169 virtual bool operator==(const BasePrimitive2D
& rPrimitive
) const override
;
171 virtual basegfx::B2DRange
getB2DRange(const geometry::ViewInformation2D
& rViewInformation
) const override
;
173 // override to allow callbacks to wrap_DoPaintObject
174 virtual void get2DDecomposition(Primitive2DDecompositionVisitor
& rVisitor
, const geometry::ViewInformation2D
& rViewInformation
) const override
;
177 const SwVirtFlyDrawObj
& getSwVirtFlyDrawObj() const { return mrSwVirtFlyDrawObj
; }
178 const basegfx::B2DRange
& getOuterRange() const { return maOuterRange
; }
180 /// provide unique ID
181 DeclPrimitive2DIDBlock()
183 } // end of namespace primitive2d
184 } // end of namespace drawinglayer
186 namespace drawinglayer
188 namespace primitive2d
190 void SwVirtFlyDrawObjPrimitive::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
192 if(!getOuterRange().isEmpty())
194 // currently this SW object has no primitive representation. As long as this is the case,
195 // create invisible geometry to allow correct HitTest and BoundRect calculations for the
196 // object. Use a filled primitive to get 'inside' as default object hit. The special cases from
197 // the old SwVirtFlyDrawObj::CheckHit implementation are handled now in SwDrawView::PickObj;
198 // this removed the 'hack' to get a view from inside model data or to react on null-tolerance
199 // as it was done in the old implementation
200 rContainer
.push_back(
201 createHiddenGeometryPrimitives2D(
207 bool SwVirtFlyDrawObjPrimitive::operator==(const BasePrimitive2D
& rPrimitive
) const
209 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
211 const SwVirtFlyDrawObjPrimitive
& rCompare
= static_cast<const SwVirtFlyDrawObjPrimitive
&>(rPrimitive
);
213 return (&getSwVirtFlyDrawObj() == &rCompare
.getSwVirtFlyDrawObj()
214 && getOuterRange() == rCompare
.getOuterRange());
220 basegfx::B2DRange
SwVirtFlyDrawObjPrimitive::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
222 return getOuterRange();
225 void SwVirtFlyDrawObjPrimitive::get2DDecomposition(Primitive2DDecompositionVisitor
& rVisitor
, const geometry::ViewInformation2D
& rViewInformation
) const
227 // This is the callback to keep the FlyFrame painting in SW alive as long as it
228 // is not changed to primitives. This is the method which will be called by the processors
229 // when they do not know this primitive (and they do not). Inside wrap_DoPaintObject
230 // there needs to be a test that paint is only done during SW repaints (see there).
231 // Using this mechanism guarantees the correct Z-Order of the VirtualObject-based FlyFrames.
232 getSwVirtFlyDrawObj().wrap_DoPaintObject(rViewInformation
);
235 BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor
, rViewInformation
);
239 ImplPrimitive2DIDBlock(SwVirtFlyDrawObjPrimitive
, PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D
)
241 } // end of namespace primitive2d
242 } // end of namespace drawinglayer
244 // AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
245 // since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
246 // For paint, that offset is used by setting at the OutputDevice; for primitives this is
247 // not possible since we have no OutputDevice, but define the geometry itself.
253 class VCOfSwVirtFlyDrawObj
: public ViewContactOfVirtObj
256 /** This method is responsible for creating the graphical visualisation data
258 * @note ONLY based on model data
260 virtual drawinglayer::primitive2d::Primitive2DContainer
createViewIndependentPrimitive2DSequence() const override
;
263 /// basic constructor, used from SdrObject.
264 explicit VCOfSwVirtFlyDrawObj(SwVirtFlyDrawObj
& rObj
)
265 : ViewContactOfVirtObj(rObj
)
269 /// access to SwVirtFlyDrawObj
270 SwVirtFlyDrawObj
& GetSwVirtFlyDrawObj() const
272 return static_cast<SwVirtFlyDrawObj
&>(mrObject
);
275 } // end of namespace contact
276 } // end of namespace sdr
282 drawinglayer::primitive2d::Primitive2DContainer
VCOfSwVirtFlyDrawObj::createViewIndependentPrimitive2DSequence() const
284 drawinglayer::primitive2d::Primitive2DContainer xRetval
;
285 const SdrObject
& rReferencedObject
= GetSwVirtFlyDrawObj().GetReferencedObj();
287 if(dynamic_cast<const SwFlyDrawObj
*>( &rReferencedObject
) != nullptr)
289 // create an own specialized primitive which is used as repaint callpoint and HitTest
290 // for HitTest processor (see primitive implementation above)
291 const basegfx::B2DRange
aOuterRange(GetSwVirtFlyDrawObj().getOuterBound());
293 if(!aOuterRange
.isEmpty())
295 const drawinglayer::primitive2d::Primitive2DReference
xPrimitive(
296 new drawinglayer::primitive2d::SwVirtFlyDrawObjPrimitive(
297 GetSwVirtFlyDrawObj(),
300 xRetval
= drawinglayer::primitive2d::Primitive2DContainer
{ xPrimitive
};
307 } // end of namespace contact
308 } // end of namespace sdr
310 basegfx::B2DRange
SwVirtFlyDrawObj::getOuterBound() const
312 basegfx::B2DRange aOuterRange
;
313 const SdrObject
& rReferencedObject
= GetReferencedObj();
315 if(dynamic_cast<const SwFlyDrawObj
*>( &rReferencedObject
) != nullptr)
317 const SwFlyFrame
* pFlyFrame
= GetFlyFrame();
321 const tools::Rectangle
aOuterRectangle(pFlyFrame
->getFrameArea().Pos(), pFlyFrame
->getFrameArea().SSize());
323 if(!aOuterRectangle
.IsEmpty())
325 aOuterRange
.expand(basegfx::B2DTuple(aOuterRectangle
.Left(), aOuterRectangle
.Top()));
326 aOuterRange
.expand(basegfx::B2DTuple(aOuterRectangle
.Right(), aOuterRectangle
.Bottom()));
334 basegfx::B2DRange
SwVirtFlyDrawObj::getInnerBound() const
336 basegfx::B2DRange aInnerRange
;
337 const SdrObject
& rReferencedObject
= GetReferencedObj();
339 if(dynamic_cast<const SwFlyDrawObj
*>( &rReferencedObject
) != nullptr)
341 const SwFlyFrame
* pFlyFrame
= GetFlyFrame();
345 const tools::Rectangle
aInnerRectangle(pFlyFrame
->getFrameArea().Pos() + pFlyFrame
->getFramePrintArea().Pos(), pFlyFrame
->getFramePrintArea().SSize());
347 if(!aInnerRectangle
.IsEmpty())
349 aInnerRange
.expand(basegfx::B2DTuple(aInnerRectangle
.Left(), aInnerRectangle
.Top()));
350 aInnerRange
.expand(basegfx::B2DTuple(aInnerRectangle
.Right(), aInnerRectangle
.Bottom()));
358 bool SwVirtFlyDrawObj::ContainsSwGrfNode() const
360 // RotGrfFlyFrame: Check if this is a SwGrfNode
361 const SwFlyFrame
* pFlyFrame(GetFlyFrame());
363 if(nullptr != pFlyFrame
&& pFlyFrame
->Lower() && pFlyFrame
->Lower()->IsNoTextFrame())
365 const SwNoTextFrame
*const pNTF(static_cast<const SwNoTextFrame
*>(pFlyFrame
->Lower()));
367 const SwGrfNode
*const pGrfNd(pNTF
->GetNode()->GetGrfNode());
369 return nullptr != pGrfNd
;
375 bool SwVirtFlyDrawObj::HasLimitedRotation() const
377 // RotGrfFlyFrame: If true, this SdrObject supports only limited rotation.
378 // This is the case for SwGrfNode instances
379 return ContainsSwGrfNode();
382 void SwVirtFlyDrawObj::Rotate(const Point
& rRef
, long nAngle
, double sn
, double cs
)
384 if(ContainsSwGrfNode())
386 // RotGrfFlyFrame: Here is where the positively completed rotate interaction is executed.
387 // Rotation is in 1/100th degree and may be signed (!)
395 SwWrtShell
*pShForAngle
= nAngle
? dynamic_cast<SwWrtShell
*>(GetFlyFrame()->getRootFrame()->GetCurrShell()) : nullptr;
398 // RotGrfFlyFrame: Add transformation to placeholder object
400 const sal_uInt16
nOldRot(SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(aSize
));
401 SwFlyFrameAttrMgr
aMgr(false, pShForAngle
, Frmmgr_Type::NONE
);
403 aMgr
.SetRotation(nOldRot
, (nOldRot
+ static_cast<sal_uInt16
>(nAngle
)) % 3600, aSize
);
409 SdrVirtObj::Rotate(rRef
, nAngle
, sn
, cs
);
413 sdr::contact::ViewContact
* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
415 // need an own ViewContact (VC) to allow creation of a specialized primitive
416 // for being able to visualize the FlyFrames in primitive renderers
417 return new sdr::contact::VCOfSwVirtFlyDrawObj(*this);
420 SwVirtFlyDrawObj::SwVirtFlyDrawObj(
424 : SdrVirtObj(rSdrModel
, rNew
),
427 const SvxProtectItem
&rP
= m_pFlyFrame
->GetFormat()->GetProtect();
428 bMovProt
= rP
.IsPosProtected();
429 bSizProt
= rP
.IsSizeProtected();
432 SwVirtFlyDrawObj::~SwVirtFlyDrawObj()
434 if ( GetPage() ) //Withdraw SdrPage the responsibility.
435 GetPage()->RemoveObject( GetOrdNum() );
438 const SwFrameFormat
*SwVirtFlyDrawObj::GetFormat() const
440 return GetFlyFrame()->GetFormat();
442 SwFrameFormat
*SwVirtFlyDrawObj::GetFormat()
444 return GetFlyFrame()->GetFormat();
453 explicit RestoreMapMode( SwViewShell
const * pViewShell
)
454 : mbMapModeRestored( false )
455 , mpOutDev( pViewShell
->GetOut() )
457 if ( pViewShell
->getPrePostMapMode() != mpOutDev
->GetMapMode() )
459 mpOutDev
->Push(PushFlags::MAPMODE
);
461 GDIMetaFile
* pMetaFile
= mpOutDev
->GetConnectMetaFile();
463 pMetaFile
->IsRecord() && !pMetaFile
->IsPause() )
465 OSL_FAIL( "MapMode restoration during meta file creation is somehow suspect - using <SetRelativeMapMode(..)>, but not sure, if correct." );
466 mpOutDev
->SetRelativeMapMode( pViewShell
->getPrePostMapMode() );
470 mpOutDev
->SetMapMode( pViewShell
->getPrePostMapMode() );
473 mbMapModeRestored
= true;
479 if ( mbMapModeRestored
)
486 bool mbMapModeRestored
;
487 VclPtr
<OutputDevice
> mpOutDev
;
492 void SwVirtFlyDrawObj::wrap_DoPaintObject(
493 drawinglayer::geometry::ViewInformation2D
const& rViewInformation
) const
495 SwViewShell
* pShell
= m_pFlyFrame
->getRootFrame()->GetCurrShell();
497 // Only paint when we have a current shell and a DrawingLayer paint is in progress.
498 // This avoids evtl. problems with renderers which do processing stuff,
499 // but no paints. IsPaintInProgress() depends on SW repaint, so, as long
500 // as SW paints self and calls DrawLayer() for Heaven and Hell, this will
502 if ( pShell
&& pShell
->IsDrawingLayerPaintInProgress() )
504 bool bDrawObject(true);
506 if ( !SwFlyFrame::IsPaint( const_cast<SwVirtFlyDrawObj
*>(this), pShell
) )
513 // if there's no viewport set, all fly-frames will be painted,
514 // which is slow, wastes memory, and can cause other trouble.
515 (void) rViewInformation
; // suppress "unused parameter" warning
516 assert(comphelper::LibreOfficeKit::isActive() || !rViewInformation
.getViewport().isEmpty());
517 if ( !m_pFlyFrame
->IsFlyInContentFrame() )
519 // it is also necessary to restore the VCL MapMode from ViewInformation since e.g.
520 // the VCL PixelRenderer resets it at the used OutputDevice. Unfortunately, this
521 // excludes shears and rotates which are not expressable in MapMode.
523 // new helper class to restore MapMode - restoration, only if
524 // needed and consideration of paint for meta file creation .
525 RestoreMapMode
aRestoreMapModeIfNeeded( pShell
);
527 // paint the FlyFrame (use standard VCL-Paint)
528 m_pFlyFrame
->PaintSwFrame( *pShell
->GetOut(), GetFlyFrame()->getFrameArea() );
534 void SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec
& rInfo
) const
537 rInfo
.bResizeFreeAllowed
= rInfo
.bResizePropAllowed
= true;
539 // RotGrfFlyFrame: Some rotation may be allowed
540 rInfo
.bRotateFreeAllowed
= rInfo
.bRotate90Allowed
= HasLimitedRotation();
542 rInfo
.bMirrorFreeAllowed
= rInfo
.bMirror45Allowed
=
543 rInfo
.bMirror90Allowed
= rInfo
.bShearAllowed
=
544 rInfo
.bCanConvToPath
= rInfo
.bCanConvToPoly
=
545 rInfo
.bCanConvToPathLineToArea
= rInfo
.bCanConvToPolyLineToArea
= false;
548 // SwVirtFlyDrawObj - Size Determination
550 void SwVirtFlyDrawObj::SetRect() const
552 if ( GetFlyFrame()->getFrameArea().HasArea() )
553 const_cast<SwVirtFlyDrawObj
*>(this)->aOutRect
= GetFlyFrame()->getFrameArea().SVRect();
555 const_cast<SwVirtFlyDrawObj
*>(this)->aOutRect
= tools::Rectangle();
558 const tools::Rectangle
& SwVirtFlyDrawObj::GetCurrentBoundRect() const
564 const tools::Rectangle
& SwVirtFlyDrawObj::GetLastBoundRect() const
566 return GetCurrentBoundRect();
569 void SwVirtFlyDrawObj::RecalcBoundRect()
574 void SwVirtFlyDrawObj::RecalcSnapRect()
579 const tools::Rectangle
& SwVirtFlyDrawObj::GetSnapRect() const
585 void SwVirtFlyDrawObj::SetSnapRect(const tools::Rectangle
& )
587 tools::Rectangle
aTmp( GetLastBoundRect() );
590 BroadcastObjectChange();
591 if (pUserCall
!=nullptr)
592 pUserCall
->Changed(*this, SdrUserCallType::Resize
, aTmp
);
595 void SwVirtFlyDrawObj::NbcSetSnapRect(const tools::Rectangle
& )
600 const tools::Rectangle
& SwVirtFlyDrawObj::GetLogicRect() const
606 void SwVirtFlyDrawObj::SetLogicRect(const tools::Rectangle
& )
608 tools::Rectangle
aTmp( GetLastBoundRect() );
611 BroadcastObjectChange();
612 if (pUserCall
!=nullptr)
613 pUserCall
->Changed(*this, SdrUserCallType::Resize
, aTmp
);
616 void SwVirtFlyDrawObj::NbcSetLogicRect(const tools::Rectangle
& )
621 ::basegfx::B2DPolyPolygon
SwVirtFlyDrawObj::TakeXorPoly() const
623 const tools::Rectangle
aSourceRectangle(GetFlyFrame()->getFrameArea().SVRect());
624 const ::basegfx::B2DRange
aSourceRange(aSourceRectangle
.Left(), aSourceRectangle
.Top(), aSourceRectangle
.Right(), aSourceRectangle
.Bottom());
625 ::basegfx::B2DPolyPolygon aRetval
;
627 aRetval
.append(::basegfx::utils::createPolygonFromRect(aSourceRange
));
632 // SwVirtFlyDrawObj::Move() and Resize()
633 void SwVirtFlyDrawObj::NbcMove(const Size
& rSiz
)
635 if(GetFlyFrame()->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame
* >(GetFlyFrame())->isTransformableSwFrame())
637 // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
638 // we need to fall back to the un-transformed state to keep the old code below
639 // working properly. Restore FrameArea and use aOutRect from old FrameArea.
640 TransformableSwFrame
* pTransformableSwFrame(static_cast<SwFlyFreeFrame
*>(GetFlyFrame())->getTransformableSwFrame());
641 pTransformableSwFrame
->restoreFrameAreas();
642 aOutRect
= GetFlyFrame()->getFrameArea().SVRect();
645 aOutRect
.Move( rSiz
);
646 const Point
aOldPos( GetFlyFrame()->getFrameArea().Pos() );
647 const Point
aNewPos( aOutRect
.TopLeft() );
648 const SwRect
aFlyRect( aOutRect
);
650 //If the Fly has a automatic align (right or top),
651 //so preserve the automatic.
652 SwFrameFormat
*pFormat
= GetFlyFrame()->GetFormat();
653 const sal_Int16 eHori
= pFormat
->GetHoriOrient().GetHoriOrient();
654 const sal_Int16 eVert
= pFormat
->GetVertOrient().GetVertOrient();
655 const sal_Int16 eRelHori
= pFormat
->GetHoriOrient().GetRelationOrient();
656 const sal_Int16 eRelVert
= pFormat
->GetVertOrient().GetRelationOrient();
657 //On paragraph bound Flys starting from the new position a new
658 //anchor must be set. Anchor and the new RelPos is calculated and
659 //placed by the Fly itself.
660 if( GetFlyFrame()->IsFlyAtContentFrame() )
662 static_cast<SwFlyAtContentFrame
*>(GetFlyFrame())->SetAbsPos( aNewPos
);
666 const SwFrameFormat
*pTmpFormat
= GetFormat();
667 const SwFormatVertOrient
&rVert
= pTmpFormat
->GetVertOrient();
668 const SwFormatHoriOrient
&rHori
= pTmpFormat
->GetHoriOrient();
669 long lXDiff
= aNewPos
.X() - aOldPos
.X();
670 if( rHori
.IsPosToggle() && text::HoriOrientation::NONE
== eHori
&&
671 !GetFlyFrame()->FindPageFrame()->OnRightPage() )
674 if( GetFlyFrame()->GetAnchorFrame()->IsRightToLeft() &&
675 text::HoriOrientation::NONE
== eHori
)
678 long lYDiff
= aNewPos
.Y() - aOldPos
.Y();
679 if( GetFlyFrame()->GetAnchorFrame()->IsVertical() )
681 //lXDiff -= rVert.GetPos();
682 //lYDiff += rHori.GetPos();
684 if ( GetFlyFrame()->GetAnchorFrame()->IsVertLR() )
686 lXDiff
+= rVert
.GetPos();
691 lXDiff
-= rVert
.GetPos();
692 lYDiff
+= rHori
.GetPos();
697 lXDiff
+= rHori
.GetPos();
698 lYDiff
+= rVert
.GetPos();
701 if( GetFlyFrame()->GetAnchorFrame()->IsRightToLeft() &&
702 text::HoriOrientation::NONE
!= eHori
)
703 lXDiff
= GetFlyFrame()->GetAnchorFrame()->getFrameArea().Width() -
704 aFlyRect
.Width() - lXDiff
;
706 const Point
aTmp( lXDiff
, lYDiff
);
707 GetFlyFrame()->ChgRelPos( aTmp
);
710 SwAttrSet
aSet( pFormat
->GetDoc()->GetAttrPool(),
711 RES_VERT_ORIENT
, RES_HORI_ORIENT
);
712 SwFormatHoriOrient
aHori( pFormat
->GetHoriOrient() );
713 SwFormatVertOrient
aVert( pFormat
->GetVertOrient() );
716 if( !GetFlyFrame()->IsFlyLayFrame() &&
717 ::GetHtmlMode(pFormat
->GetDoc()->GetDocShell()) )
719 //In HTML-Mode only automatic aligns are allowed.
720 //Only we can try a snap to left/right respectively left-/right border
721 const SwFrame
* pAnch
= GetFlyFrame()->GetAnchorFrame();
722 bool bNextLine
= false;
724 if( !GetFlyFrame()->IsAutoPos() || text::RelOrientation::PAGE_FRAME
!= aHori
.GetRelationOrient() )
726 if( text::RelOrientation::CHAR
== eRelHori
)
728 aHori
.SetHoriOrient( text::HoriOrientation::LEFT
);
729 aHori
.SetRelationOrient( text::RelOrientation::CHAR
);
735 const bool bLeftFrame
=
736 aFlyRect
.Left() < pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Left(),
737 bLeftPrt
= aFlyRect
.Left() + aFlyRect
.Width() <
738 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width()/2;
739 if ( bLeftFrame
|| bLeftPrt
)
741 aHori
.SetHoriOrient( text::HoriOrientation::LEFT
);
742 aHori
.SetRelationOrient( bLeftFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
746 const bool bRightFrame
= aFlyRect
.Left() >
747 pAnch
->getFrameArea().Left() + pAnch
->getFramePrintArea().Width();
748 aHori
.SetHoriOrient( text::HoriOrientation::RIGHT
);
749 aHori
.SetRelationOrient( bRightFrame
? text::RelOrientation::FRAME
: text::RelOrientation::PRINT_AREA
);
754 //Vertical alignment simply is retained principally,
755 //only on manual align will be switched over.
756 bool bRelChar
= text::RelOrientation::CHAR
== eRelVert
;
757 aVert
.SetVertOrient( eVert
!= text::VertOrientation::NONE
? eVert
:
758 GetFlyFrame()->IsFlyInContentFrame() ? text::VertOrientation::CHAR_CENTER
:
759 bRelChar
&& bNextLine
? text::VertOrientation::CHAR_TOP
: text::VertOrientation::TOP
);
761 aVert
.SetRelationOrient( text::RelOrientation::CHAR
);
763 aVert
.SetRelationOrient( text::RelOrientation::PRINT_AREA
);
768 //We want preferably not to lose the automatic alignments.
769 if ( !bPut
&& bInResize
)
771 if ( text::HoriOrientation::NONE
!= eHori
)
773 aHori
.SetHoriOrient( eHori
);
774 aHori
.SetRelationOrient( eRelHori
);
778 if ( text::VertOrientation::NONE
!= eVert
)
780 aVert
.SetVertOrient( eVert
);
781 aVert
.SetRelationOrient( eRelVert
);
787 pFormat
->SetFormatAttr( aSet
);
791 void SwVirtFlyDrawObj::NbcCrop(const basegfx::B2DPoint
& rRef
, double fxFact
, double fyFact
)
794 SwWrtShell
*pSh
= dynamic_cast<SwWrtShell
*>( GetFlyFrame()->getRootFrame()->GetCurrShell() );
801 GraphicObject
const *pGraphicObject
= pSh
->GetGraphicObj();
808 // Get graphic object size in 100th of mm
809 const MapMode
aMapMode100thmm(MapUnit::Map100thMM
);
810 Size
aGraphicSize(pGraphicObject
->GetPrefSize());
812 if( MapUnit::MapPixel
== pGraphicObject
->GetPrefMapMode().GetMapUnit() )
814 aGraphicSize
= Application::GetDefaultDevice()->PixelToLogic( aGraphicSize
, aMapMode100thmm
);
818 aGraphicSize
= OutputDevice::LogicToLogic( aGraphicSize
, pGraphicObject
->GetPrefMapMode(), aMapMode100thmm
);
821 if( aGraphicSize
.Width() == 0 || aGraphicSize
.Height() == 0 )
826 const bool bIsTransformableSwFrame(
827 GetFlyFrame()->IsFlyFreeFrame() &&
828 static_cast< SwFlyFreeFrame
* >(GetFlyFrame())->isTransformableSwFrame());
830 if(bIsTransformableSwFrame
)
832 // When we have a change and are in transformed state (e.g. rotation used),
833 // we need to fall back to the un-transformed state to keep the old code below
834 // working properly. Restore FrameArea and use aOutRect from old FrameArea.
835 TransformableSwFrame
* pTransformableSwFrame(static_cast<SwFlyFreeFrame
*>(GetFlyFrame())->getTransformableSwFrame());
836 pTransformableSwFrame
->restoreFrameAreas();
837 aOutRect
= GetFlyFrame()->getFrameArea().SVRect();
840 // Compute old and new rect. This will give us the deformation to apply to
841 // the object to crop. OldRect is the inner frame, see getFullDragClone()
842 // below where getFramePrintAreaTransformation is used as object geometry for Crop
843 const tools::Rectangle
aOldRect(
844 GetFlyFrame()->getFrameArea().TopLeft() + GetFlyFrame()->getFramePrintArea().TopLeft(),
845 GetFlyFrame()->getFramePrintArea().SSize());
846 const long nOldWidth(aOldRect
.GetWidth());
847 const long nOldHeight(aOldRect
.GetHeight());
849 if (!nOldWidth
|| !nOldHeight
)
854 // rRef is relative to the Crop-Action, si in X/Y-Ranges of [0.0 .. 1.0],
855 // to get the correct absolute position, transform using the old Rect
857 aOldRect
.Left() + basegfx::fround(aOldRect
.GetWidth() * rRef
.getX()),
858 aOldRect
.Top() + basegfx::fround(aOldRect
.GetHeight() * rRef
.getY()));
860 // apply transformation, use old ResizeRect for now
861 tools::Rectangle
aNewRect( aOldRect
);
868 // Get old values for crop in 10th of mm
869 SfxItemSet
aSet( pSh
->GetAttrPool(), svl::Items
<RES_GRFATR_CROPGRF
, RES_GRFATR_CROPGRF
>{} );
870 pSh
->GetCurAttr( aSet
);
871 SwCropGrf
aCrop( aSet
.Get(RES_GRFATR_CROPGRF
) );
873 tools::Rectangle
aCropRectangle(
874 convertTwipToMm100(aCrop
.GetLeft()),
875 convertTwipToMm100(aCrop
.GetTop()),
876 convertTwipToMm100(aCrop
.GetRight()),
877 convertTwipToMm100(aCrop
.GetBottom()) );
879 // Compute delta to apply
880 double fScaleX
= ( aGraphicSize
.Width() - aCropRectangle
.Left() - aCropRectangle
.Right() ) / static_cast<double>(nOldWidth
);
881 double fScaleY
= ( aGraphicSize
.Height() - aCropRectangle
.Top() - aCropRectangle
.Bottom() ) / static_cast<double>(nOldHeight
);
883 sal_Int32 nDiffLeft
= aNewRect
.Left() - aOldRect
.Left();
884 sal_Int32 nDiffTop
= aNewRect
.Top() - aOldRect
.Top();
885 sal_Int32 nDiffRight
= aNewRect
.Right() - aOldRect
.Right();
886 sal_Int32 nDiffBottom
= aNewRect
.Bottom() - aOldRect
.Bottom();
888 // Compute new values in 10th of mm
889 sal_Int32 nLeftCrop
= static_cast<sal_Int32
>( aCropRectangle
.Left() + nDiffLeft
* fScaleX
);
890 sal_Int32 nTopCrop
= static_cast<sal_Int32
>( aCropRectangle
.Top() + nDiffTop
* fScaleY
);
891 sal_Int32 nRightCrop
= static_cast<sal_Int32
>( aCropRectangle
.Right() - nDiffRight
* fScaleX
);
892 sal_Int32 nBottomCrop
= static_cast<sal_Int32
>( aCropRectangle
.Bottom() - nDiffBottom
* fScaleY
);
895 pSh
->StartAllAction();
896 // pSh->StartUndo(SwUndoId::START);
898 // Set new crop values in twips
899 aCrop
.SetLeft (convertMm100ToTwip(nLeftCrop
));
900 aCrop
.SetTop (convertMm100ToTwip(nTopCrop
));
901 aCrop
.SetRight (convertMm100ToTwip(nRightCrop
));
902 aCrop
.SetBottom(convertMm100ToTwip(nBottomCrop
));
903 pSh
->SetAttrItem(aCrop
);
905 // Set new frame size
906 SwFrameFormat
*pFormat
= GetFormat();
907 SwFormatFrameSize
aSz( pFormat
->GetFrameSize() );
908 const long aNewWidth(aNewRect
.GetWidth() + (aOutRect
.GetWidth() - aOldRect
.GetWidth()));
909 const long aNewHeight(aNewRect
.GetHeight() + (aOutRect
.GetHeight() - aOldRect
.GetHeight()));
910 aSz
.SetWidth(aNewWidth
);
911 aSz
.SetHeight(aNewHeight
);
912 pFormat
->GetDoc()->SetAttr( aSz
, *pFormat
);
914 // add move - to make result look better. Fill with defaults
915 // for the untransformed case
916 Point
aNewTopLeft(aNewRect
.TopLeft());
917 const Point
aOldTopLeft(aOldRect
.TopLeft());
919 if(bIsTransformableSwFrame
)
921 // Need to correct the NewTopLeft position in transformed state to make
922 // the interaction look correct. First, extract rotation
923 basegfx::B2DVector aScale
, aTranslate
;
924 double fRotate
, fShearX
;
925 GetFlyFrame()->getFrameAreaTransformation().decompose(aScale
, aTranslate
, fRotate
, fShearX
);
927 // calc the center of the unchanged object
928 const basegfx::B2DPoint
aFormerCenter(
929 GetFlyFrame()->getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
931 // define the existing rotation around that former center
932 const basegfx::B2DHomMatrix
aRotFormerCenter(
933 basegfx::utils::createRotateAroundPoint(
934 aFormerCenter
.getX(),
935 aFormerCenter
.getY(),
938 // use the new center of the unrotated object, rotate it around the
940 const Point
aNewCenter(aNewRect
.Center());
941 const basegfx::B2DPoint
aRotNewCenter(
942 aRotFormerCenter
* basegfx::B2DPoint(aNewCenter
.X(), aNewCenter
.Y()));
944 // Create the new TopLeft of the unrotated, cropped object by creating
945 // as if re-creating the unrotated geometry
947 basegfx::fround(aRotNewCenter
.getX() - (0.5 * aNewRect
.getWidth())),
948 basegfx::fround(aRotNewCenter
.getY() - (0.5 * aNewRect
.getHeight())));
951 // check if we have movement and execute if yes
952 const Size
aDeltaMove(
953 aNewTopLeft
.X() - aOldTopLeft
.X(),
954 aNewTopLeft
.Y() - aOldTopLeft
.Y());
956 if(0 != aDeltaMove
.Width() || 0 != aDeltaMove
.Height())
961 // pSh->EndUndo(SwUndoId::END);
965 void SwVirtFlyDrawObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
967 const SwFrame
* pTmpFrame
= GetFlyFrame()->GetAnchorFrame();
971 pTmpFrame
= GetFlyFrame();
974 const bool bVertX(pTmpFrame
->IsVertical());
975 const bool bRTL(pTmpFrame
->IsRightToLeft());
976 const bool bVertL2RX(pTmpFrame
->IsVertLR());
977 const bool bUseRightEdge((bVertX
&& !bVertL2RX
) || bRTL
);
978 const bool bIsTransformableSwFrame(
979 GetFlyFrame()->IsFlyFreeFrame() &&
980 static_cast< SwFlyFreeFrame
* >(GetFlyFrame())->isTransformableSwFrame());
982 if(bIsTransformableSwFrame
)
984 // When we have a change in transformed state, we need to fall back to the
985 // state without possible transformations.
986 // In the Resize case to correctly handle the changes, apply to the transformation
987 // and extract the new, untransformed state from that modified transformation
988 basegfx::B2DHomMatrix
aNewMat(GetFlyFrame()->getFrameAreaTransformation());
989 const basegfx::B2DPoint
aRef(rRef
.X(), rRef
.Y());
991 // apply state to already valid transformation
992 aNewMat
.translate(-aRef
.getX(), -aRef
.getY());
993 aNewMat
.scale(double(xFact
), double(yFact
));
994 aNewMat
.translate(aRef
.getX(), aRef
.getY());
996 // get center of transformed state
997 const basegfx::B2DPoint
aCenter(aNewMat
* basegfx::B2DPoint(0.5, 0.5));
999 // decompose to extract scale
1000 basegfx::B2DVector aScale
, aTranslate
;
1001 double fRotate
, fShearX
;
1002 aNewMat
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1003 const basegfx::B2DVector
aAbsScale(basegfx::absolute(aScale
));
1005 // create new modified, but untransformed OutRect
1006 aOutRect
= tools::Rectangle(
1007 basegfx::fround(aCenter
.getX() - (0.5 * aAbsScale
.getX())),
1008 basegfx::fround(aCenter
.getY() - (0.5 * aAbsScale
.getY())),
1009 basegfx::fround(aCenter
.getX() + (0.5 * aAbsScale
.getX())),
1010 basegfx::fround(aCenter
.getY() + (0.5 * aAbsScale
.getY())));
1012 // restore FrameAreas so that actions below not adapted to new
1013 // full transformations take the correct actions
1014 TransformableSwFrame
* pTransformableSwFrame(static_cast<SwFlyFreeFrame
*>(GetFlyFrame())->getTransformableSwFrame());
1015 pTransformableSwFrame
->restoreFrameAreas();
1019 ResizeRect( aOutRect
, rRef
, xFact
, yFact
);
1022 // Position may also change, remember old one. This is now already
1023 // the one in the unrotated, old coordinate system
1024 Point
aOldPos(bUseRightEdge
? GetFlyFrame()->getFrameArea().TopRight() : GetFlyFrame()->getFrameArea().Pos());
1026 // get target size in old coordinate system
1027 Size
aSz( aOutRect
.Right() - aOutRect
.Left() + 1, aOutRect
.Bottom()- aOutRect
.Top() + 1 );
1029 // compare with restored FrameArea
1030 if( aSz
!= GetFlyFrame()->getFrameArea().SSize() )
1032 //The width of the columns should not be too narrow
1033 if ( GetFlyFrame()->Lower() && GetFlyFrame()->Lower()->IsColumnFrame() )
1035 SwBorderAttrAccess
aAccess( SwFrame::GetCache(), GetFlyFrame() );
1036 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1037 long nMin
= rAttrs
.CalcLeftLine()+rAttrs
.CalcRightLine();
1038 const SwFormatCol
& rCol
= rAttrs
.GetAttrSet().GetCol();
1039 if ( rCol
.GetColumns().size() > 1 )
1041 for ( const auto &rC
: rCol
.GetColumns() )
1043 nMin
+= rC
.GetLeft() + rC
.GetRight() + MINFLY
;
1047 aSz
.setWidth( std::max( aSz
.Width(), nMin
) );
1050 SwFrameFormat
*pFormat
= GetFormat();
1051 const SwFormatFrameSize
aOldFrameSz( pFormat
->GetFrameSize() );
1052 GetFlyFrame()->ChgSize( aSz
);
1053 SwFormatFrameSize
aFrameSz( pFormat
->GetFrameSize() );
1055 if ( aFrameSz
.GetWidthPercent() || aFrameSz
.GetHeightPercent() )
1057 long nRelWidth
, nRelHeight
;
1058 const SwFrame
*pRel
= GetFlyFrame()->IsFlyLayFrame() ?
1059 GetFlyFrame()->GetAnchorFrame() :
1060 GetFlyFrame()->GetAnchorFrame()->GetUpper();
1061 const SwViewShell
*pSh
= GetFlyFrame()->getRootFrame()->GetCurrShell();
1063 if ( pSh
&& pRel
->IsBodyFrame() &&
1064 pSh
->GetViewOptions()->getBrowseMode() &&
1065 pSh
->VisArea().HasArea() )
1067 nRelWidth
= pSh
->GetBrowseWidth();
1068 nRelHeight
= pSh
->VisArea().Height();
1069 const Size aBorder
= pSh
->GetOut()->PixelToLogic( pSh
->GetBrowseBorder() );
1070 nRelHeight
-= 2*aBorder
.Height();
1074 nRelWidth
= pRel
->getFramePrintArea().Width();
1075 nRelHeight
= pRel
->getFramePrintArea().Height();
1078 if ( aFrameSz
.GetWidthPercent() && aFrameSz
.GetWidthPercent() != SwFormatFrameSize::SYNCED
&&
1079 aOldFrameSz
.GetWidth() != aFrameSz
.GetWidth() )
1081 aFrameSz
.SetWidthPercent( sal_uInt8(aSz
.Width() * 100.0 / nRelWidth
+ 0.5) );
1084 if ( aFrameSz
.GetHeightPercent() && aFrameSz
.GetHeightPercent() != SwFormatFrameSize::SYNCED
&&
1085 aOldFrameSz
.GetHeight() != aFrameSz
.GetHeight() )
1087 aFrameSz
.SetHeightPercent( sal_uInt8(aSz
.Height() * 100.0 / nRelHeight
+ 0.5) );
1090 pFormat
->GetDoc()->SetAttr( aFrameSz
, *pFormat
);
1094 //Position can also be changed, get new one
1095 const Point
aNewPos(bUseRightEdge
? aOutRect
.Right() + 1 : aOutRect
.Left(), aOutRect
.Top());
1097 if ( aNewPos
!= aOldPos
)
1099 // Former late change in aOutRect by ChgSize
1100 // is now taken into account directly by calculating
1101 // aNewPos *after* calling ChgSize (see old code).
1102 // Still need to adapt aOutRect since the 'Move' is already applied
1103 // here (see ResizeRect) and it's the same SdrObject
1104 const Size
aDeltaMove(
1105 aNewPos
.X() - aOldPos
.X(),
1106 aNewPos
.Y() - aOldPos
.Y());
1107 aOutRect
.Move(-aDeltaMove
.Width(), -aDeltaMove
.Height());
1109 // Now, move as needed (no empty delta which was a hack anyways)
1110 if(bIsTransformableSwFrame
)
1112 // need to save aOutRect to FrameArea, will be restored to aOutRect in
1113 // SwVirtFlyDrawObj::NbcMove currently for TransformableSwFrames
1114 SwFrameAreaDefinition::FrameAreaWriteAccess
aFrm(*GetFlyFrame());
1115 aFrm
.setSwRect(aOutRect
);
1118 // keep old hack - not clear what happens here
1120 NbcMove(aDeltaMove
);
1125 void SwVirtFlyDrawObj::Move(const Size
& rSiz
)
1129 GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1132 void SwVirtFlyDrawObj::Resize(const Point
& rRef
,
1133 const Fraction
& xFact
, const Fraction
& yFact
, bool /*bUnsetRelative*/)
1135 NbcResize( rRef
, xFact
, yFact
);
1137 GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1140 void SwVirtFlyDrawObj::Crop(const basegfx::B2DPoint
& rRef
, double fxFact
, double fyFact
)
1142 NbcCrop( rRef
, fxFact
, fyFact
);
1144 GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
1147 // RotGrfFlyFrame: Helper to access possible rotation of Graphic contained in FlyFrame
1148 sal_uInt16
SwVirtFlyDrawObj::getPossibleRotationFromFraphicFrame(Size
& rSize
) const
1150 sal_uInt16
nRetval(0);
1151 const SwNoTextFrame
* pNoTx
= dynamic_cast< const SwNoTextFrame
* >(GetFlyFrame()->Lower());
1155 SwNoTextNode
& rNoTNd
= const_cast< SwNoTextNode
& >(*static_cast<const SwNoTextNode
*>(pNoTx
->GetNode()));
1156 SwGrfNode
* pGrfNd
= rNoTNd
.GetGrfNode();
1158 if(nullptr != pGrfNd
)
1160 const SwAttrSet
& rSet
= pGrfNd
->GetSwAttrSet();
1161 const SwRotationGrf
& rRotation
= rSet
.GetRotationGrf();
1163 rSize
= rRotation
.GetUnrotatedSize();
1164 nRetval
= rRotation
.GetValue();
1171 SdrObject
* SwVirtFlyDrawObj::getFullDragClone() const
1174 SdrObject
* pRetval
= SdrVirtObj::getFullDragClone();
1176 if(pRetval
&& GetFlyFrame() && ContainsSwGrfNode())
1178 // RotGrfFlyFrame3: get inner bounds/transformation
1179 const basegfx::B2DHomMatrix
aTargetTransform(GetFlyFrame()->getFramePrintAreaTransformation());
1181 pRetval
->TRSetBaseGeometry(aTargetTransform
, basegfx::B2DPolyPolygon());
1187 void SwVirtFlyDrawObj::addCropHandles(SdrHdlList
& rTarget
) const
1189 // RotGrfFlyFrame: Adapt to possible rotated Graphic contained in FlyFrame
1190 if(GetFlyFrame()->getFrameArea().HasArea())
1192 // Use InnerBound, OuterBound (same as GetFlyFrame()->getFrameArea().SVRect())
1193 // may have a distance to InnerBound which needs to be taken into account.
1194 // The Graphic is mapped to InnerBound, as is the rotated Graphic.
1195 const basegfx::B2DRange
aTargetRange(getInnerBound());
1197 if(!aTargetRange
.isEmpty())
1199 // RotGrfFlyFrame3: get inner bounds/transformation
1200 const basegfx::B2DHomMatrix
aTargetTransform(GetFlyFrame()->getFramePrintAreaTransformation());
1203 basegfx::B2DTuple aScale
;
1204 basegfx::B2DTuple aTranslate
;
1205 double fRotate(0.0);
1206 double fShearX(0.0);
1207 aTargetTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1208 basegfx::B2DPoint aPos
;
1210 aPos
= aTargetTransform
* basegfx::B2DPoint(0.0, 0.0);
1211 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::UpperLeft
, fShearX
, fRotate
));
1212 aPos
= aTargetTransform
* basegfx::B2DPoint(0.5, 0.0);
1213 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::Upper
, fShearX
, fRotate
));
1214 aPos
= aTargetTransform
* basegfx::B2DPoint(1.0, 0.0);
1215 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::UpperRight
, fShearX
, fRotate
));
1216 aPos
= aTargetTransform
* basegfx::B2DPoint(0.0, 0.5);
1217 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::Left
, fShearX
, fRotate
));
1218 aPos
= aTargetTransform
* basegfx::B2DPoint(1.0, 0.5);
1219 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::Right
, fShearX
, fRotate
));
1220 aPos
= aTargetTransform
* basegfx::B2DPoint(0.0, 1.0);
1221 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::LowerLeft
, fShearX
, fRotate
));
1222 aPos
= aTargetTransform
* basegfx::B2DPoint(0.5, 1.0);
1223 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::Lower
, fShearX
, fRotate
));
1224 aPos
= aTargetTransform
* basegfx::B2DPoint(1.0, 1.0);
1225 rTarget
.AddHdl(new SdrCropHdl(Point(basegfx::fround(aPos
.getX()), basegfx::fround(aPos
.getY())), SdrHdlKind::LowerRight
, fShearX
, fRotate
));
1232 Pointer
SwVirtFlyDrawObj::GetMacroPointer(
1233 const SdrObjMacroHitRec
& ) const
1235 return Pointer( PointerStyle::RefHand
);
1238 bool SwVirtFlyDrawObj::HasMacro() const
1240 const SwFormatURL
&rURL
= m_pFlyFrame
->GetFormat()->GetURL();
1241 return rURL
.GetMap() || !rURL
.GetURL().isEmpty();
1244 SdrObject
* SwVirtFlyDrawObj::CheckMacroHit( const SdrObjMacroHitRec
& rRec
) const
1246 const SwFormatURL
&rURL
= m_pFlyFrame
->GetFormat()->GetURL();
1247 if( rURL
.GetMap() || !rURL
.GetURL().isEmpty() )
1250 if ( m_pFlyFrame
->Lower() && m_pFlyFrame
->Lower()->IsNoTextFrame() )
1252 aRect
= m_pFlyFrame
->getFramePrintArea();
1253 aRect
+= m_pFlyFrame
->getFrameArea().Pos();
1256 aRect
= m_pFlyFrame
->getFrameArea();
1258 if( aRect
.IsInside( rRec
.aPos
) )
1260 aRect
.Pos().setX(aRect
.Pos().getX() + rRec
.nTol
);
1261 aRect
.Pos().setY(aRect
.Pos().getY() + rRec
.nTol
);
1262 aRect
.SSize().AdjustHeight( -(2 * rRec
.nTol
) );
1263 aRect
.SSize().AdjustWidth( -(2 * rRec
.nTol
) );
1265 if( aRect
.IsInside( rRec
.aPos
) )
1267 if( !rURL
.GetMap() ||
1268 m_pFlyFrame
->GetFormat()->GetIMapObject( rRec
.aPos
, m_pFlyFrame
))
1269 return const_cast<SwVirtFlyDrawObj
*>(this);
1275 return SdrObject::CheckMacroHit( rRec
);
1278 bool SwVirtFlyDrawObj::IsTextBox() const
1280 return SwTextBoxHelper::isTextBox(GetFormat(), RES_FLYFRMFMT
);
1283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */