tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / svx / source / svdraw / svdorect.cxx
blobdfd04fd299b504d29e750ddcd6c67ab30842bbea
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svx/svdorect.hxx>
21 #include <svx/xpoly.hxx>
22 #include <svx/svdtrans.hxx>
23 #include <svx/svddrag.hxx>
24 #include <svx/svdmodel.hxx>
25 #include <svx/svdview.hxx>
26 #include <svx/svdopath.hxx>
27 #include <svx/dialmgr.hxx>
28 #include <svx/strings.hrc>
29 #include <sdr/properties/rectangleproperties.hxx>
30 #include <sdr/contact/viewcontactofsdrrectobj.hxx>
31 #include <tools/debug.hxx>
32 #include <vcl/ptrstyle.hxx>
33 #include <osl/diagnose.h>
35 using namespace com::sun::star;
37 // BaseProperties section
39 std::unique_ptr<sdr::properties::BaseProperties> SdrRectObj::CreateObjectSpecificProperties()
41 return std::make_unique<sdr::properties::RectangleProperties>(*this);
45 // DrawContact section
47 std::unique_ptr<sdr::contact::ViewContact> SdrRectObj::CreateObjectSpecificViewContact()
49 return std::make_unique<sdr::contact::ViewContactOfSdrRectObj>(*this);
53 SdrRectObj::SdrRectObj(SdrModel& rSdrModel)
54 : SdrTextObj(rSdrModel)
56 m_bClosedObj=true;
59 SdrRectObj::SdrRectObj(SdrModel& rSdrModel, SdrRectObj const & rSource)
60 : SdrTextObj(rSdrModel, rSource)
62 m_bClosedObj=true;
63 mpXPoly = rSource.mpXPoly;
66 SdrRectObj::SdrRectObj(
67 SdrModel& rSdrModel,
68 const tools::Rectangle& rRect)
69 : SdrTextObj(rSdrModel, rRect)
71 m_bClosedObj=true;
74 SdrRectObj::SdrRectObj(
75 SdrModel& rSdrModel,
76 SdrObjKind eNewTextKind)
77 : SdrTextObj(rSdrModel, eNewTextKind)
79 DBG_ASSERT(meTextKind == SdrObjKind::Text ||
80 meTextKind == SdrObjKind::OutlineText || meTextKind == SdrObjKind::TitleText,
81 "SdrRectObj::SdrRectObj(SdrObjKind) can only be applied to text frames.");
82 m_bClosedObj=true;
85 SdrRectObj::SdrRectObj(
86 SdrModel& rSdrModel,
87 SdrObjKind eNewTextKind,
88 const tools::Rectangle& rRect)
89 : SdrTextObj(rSdrModel, eNewTextKind, rRect)
91 DBG_ASSERT(meTextKind == SdrObjKind::Text ||
92 meTextKind == SdrObjKind::OutlineText || meTextKind == SdrObjKind::TitleText,
93 "SdrRectObj::SdrRectObj(SdrObjKind,...) can only be applied to text frames.");
94 m_bClosedObj=true;
97 SdrRectObj::~SdrRectObj()
101 void SdrRectObj::SetXPolyDirty()
103 mpXPoly.reset();
106 XPolygon SdrRectObj::ImpCalcXPoly(const tools::Rectangle& rRect1, tools::Long nRad1) const
108 XPolygon aXPoly(rRect1,nRad1,nRad1);
109 const sal_uInt16 nPointCnt(aXPoly.GetPointCount());
110 XPolygon aNewPoly(nPointCnt+1);
111 sal_uInt16 nShift=nPointCnt-2;
112 if (nRad1!=0) nShift=nPointCnt-5;
113 sal_uInt16 j=nShift;
114 for (sal_uInt16 i=1; i<nPointCnt; i++) {
115 aNewPoly[i]=aXPoly[j];
116 aNewPoly.SetFlags(i,aXPoly.GetFlags(j));
117 j++;
118 if (j>=nPointCnt) j=1;
120 aNewPoly[0]=rRect1.BottomCenter();
121 aNewPoly[nPointCnt]=aNewPoly[0];
122 aXPoly=std::move(aNewPoly);
124 // these angles always relate to the top left corner of aRect
125 if (maGeo.m_nShearAngle) ShearXPoly(aXPoly, getRectangle().TopLeft(), maGeo.mfTanShearAngle);
126 if (maGeo.m_nRotationAngle) RotateXPoly(aXPoly, getRectangle().TopLeft(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle);
127 return aXPoly;
130 void SdrRectObj::RecalcXPoly()
132 mpXPoly = ImpCalcXPoly(getRectangle(), GetEckenradius());
135 const XPolygon& SdrRectObj::GetXPoly() const
137 if(!mpXPoly)
139 const_cast<SdrRectObj*>(this)->RecalcXPoly();
142 return *mpXPoly;
145 void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
147 bool bNoTextFrame=!IsTextFrame();
148 rInfo.bResizeFreeAllowed=bNoTextFrame || ((maGeo.m_nRotationAngle.get() % 9000) == 0);
149 rInfo.bResizePropAllowed=true;
150 rInfo.bRotateFreeAllowed=true;
151 rInfo.bRotate90Allowed =true;
152 rInfo.bMirrorFreeAllowed=bNoTextFrame;
153 rInfo.bMirror45Allowed =bNoTextFrame;
154 rInfo.bMirror90Allowed =bNoTextFrame;
156 // allow transparency
157 rInfo.bTransparenceAllowed = true;
159 rInfo.bShearAllowed =bNoTextFrame;
160 rInfo.bEdgeRadiusAllowed=true;
162 bool bCanConv=!HasText() || ImpCanConvTextToCurve();
163 if (bCanConv && !bNoTextFrame && !HasText()) {
164 bCanConv=HasFill() || HasLine();
166 rInfo.bCanConvToPath =bCanConv;
167 rInfo.bCanConvToPoly =bCanConv;
168 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
171 SdrObjKind SdrRectObj::GetObjIdentifier() const
173 if (IsTextFrame())
174 return meTextKind;
175 else return SdrObjKind::Rectangle;
178 void SdrRectObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const
180 rRect = getRectangle();
181 if (maGeo.m_nShearAngle==0_deg100)
182 return;
184 tools::Long nDst=basegfx::fround<tools::Long>((getRectangle().Bottom()-getRectangle().Top()) * maGeo.mfTanShearAngle);
185 if (maGeo.m_nShearAngle>0_deg100)
187 Point aRef(rRect.TopLeft());
188 rRect.AdjustLeft( -nDst );
189 Point aTmpPt(rRect.TopLeft());
190 RotatePoint(aTmpPt,aRef,maGeo.mfSinRotationAngle,maGeo.mfCosRotationAngle);
191 aTmpPt-=rRect.TopLeft();
192 rRect.Move(aTmpPt.X(),aTmpPt.Y());
194 else
196 rRect.AdjustRight( -nDst );
200 OUString SdrRectObj::TakeObjNameSingul() const
202 if (IsTextFrame())
204 return SdrTextObj::TakeObjNameSingul();
207 bool bRounded = GetEckenradius() != 0; // rounded down
208 TranslateId pResId = bRounded ? STR_ObjNameSingulRECTRND : STR_ObjNameSingulRECT;
209 if (maGeo.m_nShearAngle)
211 pResId = bRounded ? STR_ObjNameSingulPARALRND : STR_ObjNameSingulPARAL; // parallelogram or, maybe, rhombus
213 else if (getRectangle().GetWidth() == getRectangle().GetHeight())
215 pResId = bRounded ? STR_ObjNameSingulQUADRND : STR_ObjNameSingulQUAD; // square
217 OUString sName(SvxResId(pResId));
219 OUString aName(GetName());
220 if (!aName.isEmpty())
221 sName += " '" + aName + "'";
223 return sName;
226 OUString SdrRectObj::TakeObjNamePlural() const
228 if (IsTextFrame())
230 return SdrTextObj::TakeObjNamePlural();
233 bool bRounded = GetEckenradius() != 0; // rounded down
234 TranslateId pResId = bRounded ? STR_ObjNamePluralRECTRND : STR_ObjNamePluralRECT;
235 if (maGeo.m_nShearAngle)
237 pResId = bRounded ? STR_ObjNamePluralPARALRND : STR_ObjNamePluralPARAL; // parallelogram or rhombus
239 else if (getRectangle().GetWidth() == getRectangle().GetHeight())
241 pResId = bRounded ? STR_ObjNamePluralQUADRND : STR_ObjNamePluralQUAD; // square
244 return SvxResId(pResId);
247 rtl::Reference<SdrObject> SdrRectObj::CloneSdrObject(SdrModel& rTargetModel) const
249 return new SdrRectObj(rTargetModel, *this);
252 basegfx::B2DPolyPolygon SdrRectObj::TakeXorPoly() const
254 XPolyPolygon aXPP;
255 aXPP.Insert(ImpCalcXPoly(getRectangle(), GetEckenradius()));
256 return aXPP.getB2DPolyPolygon();
259 void SdrRectObj::RecalcSnapRect()
261 tools::Long nEckRad=GetEckenradius();
262 if ((maGeo.m_nRotationAngle || maGeo.m_nShearAngle) && nEckRad!=0) {
263 maSnapRect=GetXPoly().GetBoundRect();
264 } else {
265 SdrTextObj::RecalcSnapRect();
269 void SdrRectObj::NbcSetSnapRect(const tools::Rectangle& rRect)
271 SdrTextObj::NbcSetSnapRect(rRect);
272 SetXPolyDirty();
275 void SdrRectObj::NbcSetLogicRect(const tools::Rectangle& rRect, bool bAdaptTextMinSize)
277 SdrTextObj::NbcSetLogicRect(rRect, bAdaptTextMinSize);
278 SetXPolyDirty();
281 sal_uInt32 SdrRectObj::GetHdlCount() const
283 return IsTextFrame() ? 10 : 9;
286 void SdrRectObj::AddToHdlList(SdrHdlList& rHdlList) const
288 // A text box has an additional (pseudo-)handle for the blinking frame.
289 if(IsTextFrame())
291 OSL_ENSURE(!IsTextEditActive(), "Do not use an ImpTextframeHdl for highlighting text in active text edit, this will collide with EditEngine paints (!)");
292 std::unique_ptr<SdrHdl> pH(new ImpTextframeHdl(getRectangle()));
293 pH->SetObj(const_cast<SdrRectObj*>(this));
294 pH->SetRotationAngle(maGeo.m_nRotationAngle);
295 rHdlList.AddHdl(std::move(pH));
298 for(sal_Int32 nHdlNum = 1; nHdlNum <= 9; ++nHdlNum)
300 Point aPnt;
301 SdrHdlKind eKind = SdrHdlKind::Move;
302 auto const& rRectangle = getRectangle();
303 switch(nHdlNum)
305 case 1: // Handle for changing the corner radius
307 tools::Long a = GetEckenradius();
308 tools::Long b = std::max(rRectangle.GetWidth(), rRectangle.GetHeight())/2; // rounded up, because GetWidth() adds 1
309 if (a>b) a=b;
310 if (a<0) a=0;
311 aPnt = rRectangle.TopLeft();
312 aPnt.AdjustX(a );
313 eKind = SdrHdlKind::Circle;
314 break;
316 case 2: aPnt = rRectangle.TopLeft(); eKind = SdrHdlKind::UpperLeft; break;
317 case 3: aPnt = rRectangle.TopCenter(); eKind = SdrHdlKind::Upper; break;
318 case 4: aPnt = rRectangle.TopRight(); eKind = SdrHdlKind::UpperRight; break;
319 case 5: aPnt = rRectangle.LeftCenter(); eKind = SdrHdlKind::Left ; break;
320 case 6: aPnt = rRectangle.RightCenter(); eKind = SdrHdlKind::Right; break;
321 case 7: aPnt = rRectangle.BottomLeft(); eKind = SdrHdlKind::LowerLeft; break;
322 case 8: aPnt = rRectangle.BottomCenter(); eKind = SdrHdlKind::Lower; break;
323 case 9: aPnt = rRectangle.BottomRight(); eKind = SdrHdlKind::LowerRight; break;
326 if (maGeo.m_nShearAngle)
328 ShearPoint(aPnt,rRectangle.TopLeft(),maGeo.mfTanShearAngle);
330 if (maGeo.m_nRotationAngle)
332 RotatePoint(aPnt,rRectangle.TopLeft(),maGeo.mfSinRotationAngle,maGeo.mfCosRotationAngle);
335 std::unique_ptr<SdrHdl> pH(new SdrHdl(aPnt,eKind));
336 pH->SetObj(const_cast<SdrRectObj*>(this));
337 pH->SetRotationAngle(maGeo.m_nRotationAngle);
338 rHdlList.AddHdl(std::move(pH));
342 bool SdrRectObj::hasSpecialDrag() const
344 return true;
347 bool SdrRectObj::beginSpecialDrag(SdrDragStat& rDrag) const
349 const bool bRad(rDrag.GetHdl() && SdrHdlKind::Circle == rDrag.GetHdl()->GetKind());
351 if(bRad)
353 rDrag.SetEndDragChangesAttributes(true);
355 return true;
358 return SdrTextObj::beginSpecialDrag(rDrag);
361 bool SdrRectObj::applySpecialDrag(SdrDragStat& rDrag)
363 const bool bRad(rDrag.GetHdl() && SdrHdlKind::Circle == rDrag.GetHdl()->GetKind());
365 if (bRad)
367 Point aPt(rDrag.GetNow());
369 if (maGeo.m_nRotationAngle)
370 RotatePoint(aPt, getRectangle().TopLeft(), -maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle);
372 sal_Int32 nRad(aPt.X() - getRectangle().Left());
374 if (nRad < 0)
375 nRad = 0;
377 if(nRad != GetEckenradius())
379 NbcSetEckenradius(nRad);
382 return true;
384 else
386 return SdrTextObj::applySpecialDrag(rDrag);
390 OUString SdrRectObj::getSpecialDragComment(const SdrDragStat& rDrag) const
392 const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
394 if(bCreateComment)
396 return OUString();
398 else
400 const bool bRad(rDrag.GetHdl() && SdrHdlKind::Circle == rDrag.GetHdl()->GetKind());
402 if(bRad)
404 Point aPt(rDrag.GetNow());
406 // -sin for reversal
407 if (maGeo.m_nRotationAngle)
408 RotatePoint(aPt, getRectangle().TopLeft(), -maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle);
410 sal_Int32 nRad(aPt.X() - getRectangle().Left());
412 if(nRad < 0)
413 nRad = 0;
415 return ImpGetDescriptionStr(STR_DragRectEckRad) +
416 " (" +
417 GetMetrStr(nRad) +
418 ")";
420 else
422 return SdrTextObj::getSpecialDragComment(rDrag);
428 basegfx::B2DPolyPolygon SdrRectObj::TakeCreatePoly(const SdrDragStat& rDrag) const
430 tools::Rectangle aRect1;
431 rDrag.TakeCreateRect(aRect1);
432 aRect1.Normalize();
434 basegfx::B2DPolyPolygon aRetval;
435 aRetval.append(ImpCalcXPoly(aRect1,GetEckenradius()).getB2DPolygon());
436 return aRetval;
439 PointerStyle SdrRectObj::GetCreatePointer() const
441 if (IsTextFrame()) return PointerStyle::DrawText;
442 return PointerStyle::DrawRect;
445 void SdrRectObj::NbcMove(const Size& rSiz)
447 SdrTextObj::NbcMove(rSiz);
448 SetXPolyDirty();
451 void SdrRectObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
453 SdrTextObj::NbcResize(rRef,xFact,yFact);
454 SetXPolyDirty();
457 void SdrRectObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
459 SdrTextObj::NbcRotate(rRef,nAngle,sn,cs);
460 SetXPolyDirty();
463 void SdrRectObj::NbcShear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
465 SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear);
466 SetXPolyDirty();
469 void SdrRectObj::NbcMirror(const Point& rRef1, const Point& rRef2)
471 SdrTextObj::NbcMirror(rRef1,rRef2);
472 SetXPolyDirty();
475 SdrGluePoint SdrRectObj::GetVertexGluePoint(sal_uInt16 nPosNum) const
477 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#
479 // #i25616#
480 if(!LineIsOutsideGeometry())
482 nWdt++;
483 nWdt /= 2;
486 Point aPt;
487 auto const& rRectangle = getRectangle();
488 switch (nPosNum) {
489 case 0: aPt = rRectangle.TopCenter(); aPt.AdjustY( -nWdt ); break;
490 case 1: aPt = rRectangle.RightCenter(); aPt.AdjustX(nWdt ); break;
491 case 2: aPt = rRectangle.BottomCenter(); aPt.AdjustY(nWdt ); break;
492 case 3: aPt = rRectangle.LeftCenter(); aPt.AdjustX( -nWdt ); break;
494 if (maGeo.m_nShearAngle)
495 ShearPoint(aPt, rRectangle.TopLeft(), maGeo.mfTanShearAngle);
496 if (maGeo.m_nRotationAngle)
497 RotatePoint(aPt, rRectangle.TopLeft(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle);
498 aPt-=GetSnapRect().Center();
499 SdrGluePoint aGP(aPt);
500 aGP.SetPercent(false);
501 return aGP;
504 SdrGluePoint SdrRectObj::GetCornerGluePoint(sal_uInt16 nPosNum) const
506 sal_Int32 nWdt = ImpGetLineWdt(); // #i25616#
508 // #i25616#
509 if(!LineIsOutsideGeometry())
511 nWdt++;
512 nWdt /= 2;
515 Point aPt;
516 auto const& rRectangle = getRectangle();
517 switch (nPosNum) {
518 case 0: aPt = rRectangle.TopLeft(); aPt.AdjustX( -nWdt ); aPt.AdjustY( -nWdt ); break;
519 case 1: aPt = rRectangle.TopRight(); aPt.AdjustX(nWdt ); aPt.AdjustY( -nWdt ); break;
520 case 2: aPt = rRectangle.BottomRight(); aPt.AdjustX(nWdt ); aPt.AdjustY(nWdt ); break;
521 case 3: aPt = rRectangle.BottomLeft(); aPt.AdjustX( -nWdt ); aPt.AdjustY(nWdt ); break;
523 if (maGeo.m_nShearAngle)
524 ShearPoint(aPt, rRectangle.TopLeft(),maGeo.mfTanShearAngle);
525 if (maGeo.m_nRotationAngle)
526 RotatePoint(aPt, rRectangle.TopLeft(),maGeo.mfSinRotationAngle,maGeo.mfCosRotationAngle);
527 aPt-=GetSnapRect().Center();
528 SdrGluePoint aGP(aPt);
529 aGP.SetPercent(false);
530 return aGP;
533 rtl::Reference<SdrObject> SdrRectObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
535 XPolygon aXP(ImpCalcXPoly(getRectangle(), GetEckenradius()));
536 { // TODO: this is only for the moment, until we have the new TakeContour()
537 aXP.Remove(0,1);
538 aXP[aXP.GetPointCount()-1]=aXP[0];
541 basegfx::B2DPolyPolygon aPolyPolygon(aXP.getB2DPolygon());
542 aPolyPolygon.removeDoublePoints();
543 rtl::Reference<SdrObject> pRet;
545 // small correction: Do not create something when no fill and no line. To
546 // be sure to not damage something with non-text frames, do this only
547 // when used with bAddText==false from other converters
548 if((bAddText && !IsTextFrame()) || HasFill() || HasLine())
550 pRet = ImpConvertMakeObj(aPolyPolygon, true, bBezier);
553 if(bAddText)
555 pRet = ImpConvertAddText(std::move(pRet), bBezier);
558 return pRet;
561 void SdrRectObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
563 SdrTextObj::Notify(rBC,rHint);
564 SetXPolyDirty(); // because of the corner radius
567 void SdrRectObj::RestoreGeoData(const SdrObjGeoData& rGeo)
569 SdrTextObj::RestoreGeoData(rGeo);
570 SetXPolyDirty();
573 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */