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 .
21 #include <comphelper/string.hxx>
22 #include <svx/svdotext.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdview.hxx>
25 #include <svx/svdpage.hxx>
26 #include <svx/svdetc.hxx>
27 #include <svx/svdoutl.hxx>
28 #include <svx/svdmodel.hxx>
29 #include <svx/dialmgr.hxx>
30 #include <svx/strings.hrc>
31 #include <editeng/writingmodeitem.hxx>
32 #include <svx/sdtfchim.hxx>
33 #include <svtools/colorcfg.hxx>
34 #include <editeng/editdata.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/editstat.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <editeng/editobj.hxx>
39 #include <editeng/outliner.hxx>
40 #include <editeng/fhgtitem.hxx>
41 #include <svx/textchain.hxx>
42 #include <svx/textchainflow.hxx>
43 #include <svl/itempool.hxx>
44 #include <editeng/adjustitem.hxx>
45 #include <editeng/flditem.hxx>
46 #include <svx/xftouit.hxx>
47 #include <tools/helpers.hxx>
48 #include <svx/xflgrit.hxx>
49 #include <svx/svdpool.hxx>
50 #include <svx/xflclit.hxx>
51 #include <svl/style.hxx>
52 #include <svx/sderitm.hxx>
53 #include <svx/sdooitm.hxx>
54 #include <svx/sdshitm.hxx>
55 #include <svx/sdtagitm.hxx>
56 #include <svx/sdtfsitm.hxx>
57 #include <svx/sdtmfitm.hxx>
58 #include <svx/xtextit0.hxx>
59 #include <editeng/editeng.hxx>
60 #include <svl/itemiter.hxx>
61 #include <sdr/properties/textproperties.hxx>
62 #include <vcl/metaact.hxx>
63 #include <svx/sdr/contact/viewcontactoftextobj.hxx>
64 #include <basegfx/tuple/b2dtuple.hxx>
65 #include <basegfx/matrix/b2dhommatrix.hxx>
66 #include <basegfx/polygon/b2dpolygon.hxx>
67 #include <drawinglayer/geometry/viewinformation2d.hxx>
68 #include <vcl/virdev.hxx>
69 #include <basegfx/matrix/b2dhommatrixtools.hxx>
70 #include <sal/log.hxx>
72 using namespace com::sun::star
;
74 // BaseProperties section
75 std::unique_ptr
<sdr::properties::BaseProperties
> SdrTextObj::CreateObjectSpecificProperties()
77 return std::make_unique
<sdr::properties::TextProperties
>(*this);
80 // DrawContact section
81 std::unique_ptr
<sdr::contact::ViewContact
> SdrTextObj::CreateObjectSpecificViewContact()
83 return std::make_unique
<sdr::contact::ViewContactOfTextObj
>(*this);
86 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
)
87 : SdrAttrObj(rSdrModel
),
94 bDisableAutoWidthOnDragging
=false;
97 mbTextAnimationAllowed
= true;
98 maTextEditOffset
= Point(0, 0);
101 mbSupportTextIndentingOnLineWidthChange
= true;
102 mbInDownScale
= false;
105 SdrTextObj::SdrTextObj(
107 const tools::Rectangle
& rNewRect
)
108 : SdrAttrObj(rSdrModel
),
113 bTextSizeDirty
=false;
116 bDisableAutoWidthOnDragging
=false;
117 ImpJustifyRect(maRect
);
119 mbInEditMode
= false;
120 mbTextAnimationAllowed
= true;
121 mbInDownScale
= false;
122 maTextEditOffset
= Point(0, 0);
125 mbSupportTextIndentingOnLineWidthChange
= true;
128 SdrTextObj::SdrTextObj(
130 SdrObjKind eNewTextKind
)
131 : SdrAttrObj(rSdrModel
),
133 eTextKind(eNewTextKind
)
135 bTextSizeDirty
=false;
138 bDisableAutoWidthOnDragging
=false;
140 mbInEditMode
= false;
141 mbTextAnimationAllowed
= true;
142 mbInDownScale
= false;
143 maTextEditOffset
= Point(0, 0);
146 mbSupportTextIndentingOnLineWidthChange
= true;
149 SdrTextObj::SdrTextObj(
151 SdrObjKind eNewTextKind
,
152 const tools::Rectangle
& rNewRect
)
153 : SdrAttrObj(rSdrModel
),
156 eTextKind(eNewTextKind
)
158 bTextSizeDirty
=false;
161 bDisableAutoWidthOnDragging
=false;
162 ImpJustifyRect(maRect
);
164 mbInEditMode
= false;
165 mbTextAnimationAllowed
= true;
166 mbInDownScale
= false;
167 maTextEditOffset
= Point(0, 0);
170 mbSupportTextIndentingOnLineWidthChange
= true;
173 SdrTextObj::~SdrTextObj()
175 SdrOutliner
& rOutl(getSdrModelFromSdrObject().GetHitTestOutliner());
176 if( rOutl
.GetTextObj() == this )
177 rOutl
.SetTextObj( nullptr );
182 void SdrTextObj::FitFrameToTextSize()
184 ImpJustifyRect(maRect
);
186 SdrText
* pText
= getActiveText();
187 if(pText
==nullptr || !pText
->GetOutlinerParaObject())
190 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
191 rOutliner
.SetPaperSize(Size(maRect
.Right()-maRect
.Left(),maRect
.Bottom()-maRect
.Top()));
192 rOutliner
.SetUpdateMode(true);
193 rOutliner
.SetText(*pText
->GetOutlinerParaObject());
194 Size
aNewSize(rOutliner
.CalcTextSize());
196 aNewSize
.AdjustWidth( 1 ); // because of possible rounding errors
197 aNewSize
.AdjustWidth(GetTextLeftDistance()+GetTextRightDistance() );
198 aNewSize
.AdjustHeight(GetTextUpperDistance()+GetTextLowerDistance() );
199 tools::Rectangle
aNewRect(maRect
);
200 aNewRect
.SetSize(aNewSize
);
201 ImpJustifyRect(aNewRect
);
202 if (aNewRect
!=maRect
) {
203 SetLogicRect(aNewRect
);
207 void SdrTextObj::NbcSetText(const OUString
& rStr
)
209 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
210 rOutliner
.SetStyleSheet( 0, GetStyleSheet());
211 rOutliner
.SetUpdateMode(true);
212 rOutliner
.SetText(rStr
,rOutliner
.GetParagraph( 0 ));
213 std::unique_ptr
<OutlinerParaObject
> pNewText
=rOutliner
.CreateParaObject();
214 Size
aSiz(rOutliner
.CalcTextSize());
216 NbcSetOutlinerParaObject(std::move(pNewText
));
218 bTextSizeDirty
=false;
221 void SdrTextObj::SetText(const OUString
& rStr
)
223 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
226 BroadcastObjectChange();
227 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
230 void SdrTextObj::NbcSetText(SvStream
& rInput
, const OUString
& rBaseURL
, EETextFormat eFormat
)
232 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
233 rOutliner
.SetStyleSheet( 0, GetStyleSheet());
234 rOutliner
.Read(rInput
,rBaseURL
,eFormat
);
235 std::unique_ptr
<OutlinerParaObject
> pNewText
=rOutliner
.CreateParaObject();
236 rOutliner
.SetUpdateMode(true);
237 Size
aSiz(rOutliner
.CalcTextSize());
239 NbcSetOutlinerParaObject(std::move(pNewText
));
241 bTextSizeDirty
=false;
244 void SdrTextObj::SetText(SvStream
& rInput
, const OUString
& rBaseURL
, EETextFormat eFormat
)
246 tools::Rectangle aBoundRect0
; if (pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
247 NbcSetText(rInput
,rBaseURL
,eFormat
);
249 BroadcastObjectChange();
250 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
253 const Size
& SdrTextObj::GetTextSize() const
258 SdrText
* pText
= getActiveText();
259 if( pText
&& pText
->GetOutlinerParaObject ())
261 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
262 rOutliner
.SetText(*pText
->GetOutlinerParaObject());
263 rOutliner
.SetUpdateMode(true);
264 aSiz
=rOutliner
.CalcTextSize();
267 // casting to nonconst twice
268 const_cast<SdrTextObj
*>(this)->aTextSize
=aSiz
;
269 const_cast<SdrTextObj
*>(this)->bTextSizeDirty
=false;
274 bool SdrTextObj::IsAutoGrowHeight() const
277 return false; // AutoGrow only together with TextFrames
279 const SfxItemSet
& rSet
= GetObjectItemSet();
280 bool bRet
= rSet
.Get(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
284 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
286 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
288 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
290 if(eDirection
== SdrTextAniDirection::Up
|| eDirection
== SdrTextAniDirection::Down
)
299 bool SdrTextObj::IsAutoGrowWidth() const
302 return false; // AutoGrow only together with TextFrames
304 const SfxItemSet
& rSet
= GetObjectItemSet();
305 bool bRet
= rSet
.Get(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue();
307 bool bInEditMOde
= IsInEditMode();
309 if(!bInEditMOde
&& bRet
)
311 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
313 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
315 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
317 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
326 SdrTextHorzAdjust
SdrTextObj::GetTextHorizontalAdjust() const
328 return GetTextHorizontalAdjust(GetObjectItemSet());
331 SdrTextHorzAdjust
SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet
& rSet
) const
333 if(IsContourTextFrame())
334 return SDRTEXTHORZADJUST_BLOCK
;
336 SdrTextHorzAdjust eRet
= rSet
.Get(SDRATTR_TEXT_HORZADJUST
).GetValue();
338 bool bInEditMode
= IsInEditMode();
340 if(!bInEditMode
&& eRet
== SDRTEXTHORZADJUST_BLOCK
)
342 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
344 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
346 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
348 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
350 eRet
= SDRTEXTHORZADJUST_LEFT
;
356 } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
358 SdrTextVertAdjust
SdrTextObj::GetTextVerticalAdjust() const
360 return GetTextVerticalAdjust(GetObjectItemSet());
363 SdrTextVertAdjust
SdrTextObj::GetTextVerticalAdjust(const SfxItemSet
& rSet
) const
365 if(IsContourTextFrame())
366 return SDRTEXTVERTADJUST_TOP
;
368 // Take care for vertical text animation here
369 SdrTextVertAdjust eRet
= rSet
.Get(SDRATTR_TEXT_VERTADJUST
).GetValue();
370 bool bInEditMode
= IsInEditMode();
372 // Take care for vertical text animation here
373 if(!bInEditMode
&& eRet
== SDRTEXTVERTADJUST_BLOCK
)
375 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
377 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
379 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
381 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
383 eRet
= SDRTEXTVERTADJUST_TOP
;
389 } // defaults: TOP for text frame, CENTER for captions of drawing objects
391 void SdrTextObj::ImpJustifyRect(tools::Rectangle
& rRect
)
393 if (!rRect
.IsEmpty()) {
395 if (rRect
.Left()==rRect
.Right()) rRect
.AdjustRight( 1 );
396 if (rRect
.Top()==rRect
.Bottom()) rRect
.AdjustBottom( 1 );
400 void SdrTextObj::ImpCheckShear()
402 if (bNoShear
&& aGeo
.nShearAngle
!=0) {
408 void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
410 bool bNoTextFrame
=!IsTextFrame();
411 rInfo
.bResizeFreeAllowed
=bNoTextFrame
|| aGeo
.nRotationAngle
%9000==0;
412 rInfo
.bResizePropAllowed
=true;
413 rInfo
.bRotateFreeAllowed
=true;
414 rInfo
.bRotate90Allowed
=true;
415 rInfo
.bMirrorFreeAllowed
=bNoTextFrame
;
416 rInfo
.bMirror45Allowed
=bNoTextFrame
;
417 rInfo
.bMirror90Allowed
=bNoTextFrame
;
419 // allow transparency
420 rInfo
.bTransparenceAllowed
= true;
422 rInfo
.bShearAllowed
=bNoTextFrame
;
423 rInfo
.bEdgeRadiusAllowed
=true;
424 bool bCanConv
=ImpCanConvTextToCurve();
425 rInfo
.bCanConvToPath
=bCanConv
;
426 rInfo
.bCanConvToPoly
=bCanConv
;
427 rInfo
.bCanConvToPathLineToArea
=bCanConv
;
428 rInfo
.bCanConvToPolyLineToArea
=bCanConv
;
429 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
432 sal_uInt16
SdrTextObj::GetObjIdentifier() const
434 return sal_uInt16(eTextKind
);
437 bool SdrTextObj::HasTextImpl( SdrOutliner
const * pOutliner
)
442 Paragraph
* p1stPara
=pOutliner
->GetParagraph( 0 );
443 sal_Int32 nParaCount
=pOutliner
->GetParagraphCount();
444 if(p1stPara
==nullptr)
449 // if it is only one paragraph, check if that paragraph is empty
450 if( pOutliner
->GetText(p1stPara
).isEmpty() )
459 void SdrTextObj::handlePageChange(SdrPage
* pOldPage
, SdrPage
* pNewPage
)
461 const bool bRemove(pNewPage
== nullptr && pOldPage
!= nullptr);
462 const bool bInsert(pNewPage
!= nullptr && pOldPage
== nullptr);
463 const bool bLinked(IsLinkedText());
465 if (bLinked
&& bRemove
)
471 SdrAttrObj::handlePageChange(pOldPage
, pNewPage
);
473 if (bLinked
&& bInsert
)
479 void SdrTextObj::NbcSetEckenradius(long nRad
)
481 SetObjectItem(makeSdrEckenradiusItem(nRad
));
484 // #115391# This implementation is based on the object size (aRect) and the
485 // states of IsAutoGrowWidth/Height to correctly set TextMinFrameWidth/Height
486 void SdrTextObj::AdaptTextMinSize()
489 // Only do this for text frame.
492 if (getSdrModelFromSdrObject().IsPasteResize())
493 // Don't do this during paste resize.
496 const bool bW
= IsAutoGrowWidth();
497 const bool bH
= IsAutoGrowHeight();
500 // No auto grow requested. Bail out.
504 *GetObjectItemSet().GetPool(),
505 svl::Items
<SDRATTR_TEXT_MINFRAMEHEIGHT
, SDRATTR_TEXT_AUTOGROWHEIGHT
,
506 SDRATTR_TEXT_MINFRAMEWIDTH
, SDRATTR_TEXT_AUTOGROWWIDTH
>{}); // contains SDRATTR_TEXT_MAXFRAMEWIDTH
510 // Set minimum width.
511 const long nDist
= GetTextLeftDistance() + GetTextRightDistance();
512 const long nW
= std::max
<long>(0, maRect
.GetWidth() - 1 - nDist
); // text width without margins
514 aSet
.Put(makeSdrTextMinFrameWidthItem(nW
));
516 if(!IsVerticalWriting() && bDisableAutoWidthOnDragging
)
518 bDisableAutoWidthOnDragging
= true;
519 aSet
.Put(makeSdrTextAutoGrowWidthItem(false));
525 // Set Minimum height.
526 const long nDist
= GetTextUpperDistance() + GetTextLowerDistance();
527 const long nH
= std::max
<long>(0, maRect
.GetHeight() - 1 - nDist
); // text height without margins
529 aSet
.Put(makeSdrTextMinFrameHeightItem(nH
));
531 if(IsVerticalWriting() && bDisableAutoWidthOnDragging
)
533 bDisableAutoWidthOnDragging
= false;
534 aSet
.Put(makeSdrTextAutoGrowHeightItem(false));
538 SetObjectItemSet(aSet
);
541 void SdrTextObj::ImpSetContourPolygon( SdrOutliner
& rOutliner
, tools::Rectangle
const & rAnchorRect
, bool bLineWidth
) const
543 basegfx::B2DPolyPolygon
aXorPolyPolygon(TakeXorPoly());
544 std::unique_ptr
<basegfx::B2DPolyPolygon
> pContourPolyPolygon
;
545 basegfx::B2DHomMatrix
aMatrix(basegfx::utils::createTranslateB2DHomMatrix(
546 -rAnchorRect
.Left(), -rAnchorRect
.Top()));
548 if(aGeo
.nRotationAngle
)
551 aMatrix
.rotate(-aGeo
.nRotationAngle
* F_PI18000
);
554 aXorPolyPolygon
.transform(aMatrix
);
558 // Take line width into account.
559 // When doing the hit test, avoid this. (Performance!)
560 pContourPolyPolygon
.reset(new basegfx::B2DPolyPolygon());
562 // test if shadow needs to be avoided for TakeContour()
563 const SfxItemSet
& rSet
= GetObjectItemSet();
564 bool bShadowOn
= rSet
.Get(SDRATTR_SHADOW
).GetValue();
567 // Remember TextObject currently set at the DrawOutliner, it WILL be
568 // replaced during calculating the outline since it uses an own paint
569 // and that one uses the DrawOutliner, too.
570 const SdrTextObj
* pLastTextObject
= rOutliner
.GetTextObj();
575 SdrObject
* pCopy(CloneSdrObject(getSdrModelFromSdrObject()));
576 pCopy
->SetMergedItem(makeSdrShadowItem(false));
577 *pContourPolyPolygon
= pCopy
->TakeContour();
578 SdrObject::Free( pCopy
);
582 *pContourPolyPolygon
= TakeContour();
586 // restore remembered text object
587 if(pLastTextObject
!= rOutliner
.GetTextObj())
589 rOutliner
.SetTextObj(pLastTextObject
);
592 pContourPolyPolygon
->transform(aMatrix
);
595 rOutliner
.SetPolygon(aXorPolyPolygon
, pContourPolyPolygon
.get());
598 void SdrTextObj::TakeUnrotatedSnapRect(tools::Rectangle
& rRect
) const
603 void SdrTextObj::TakeTextAnchorRect(tools::Rectangle
& rAnchorRect
) const
605 long nLeftDist
=GetTextLeftDistance();
606 long nRightDist
=GetTextRightDistance();
607 long nUpperDist
=GetTextUpperDistance();
608 long nLowerDist
=GetTextLowerDistance();
609 tools::Rectangle
aAnkRect(maRect
); // the rectangle in which we anchor
610 bool bFrame
=IsTextFrame();
612 TakeUnrotatedSnapRect(aAnkRect
);
614 Point
aRotateRef(aAnkRect
.TopLeft());
615 aAnkRect
.AdjustLeft(nLeftDist
);
616 aAnkRect
.AdjustTop(nUpperDist
);
617 aAnkRect
.AdjustRight( -nRightDist
);
618 aAnkRect
.AdjustBottom( -nLowerDist
);
620 // Since sizes may be bigger than the object bounds it is necessary to
621 // justify the rect now.
622 ImpJustifyRect(aAnkRect
);
625 // TODO: Optimize this.
626 if (aAnkRect
.GetWidth()<2) aAnkRect
.SetRight(aAnkRect
.Left()+1 ); // minimum size h and v: 2 px
627 if (aAnkRect
.GetHeight()<2) aAnkRect
.SetBottom(aAnkRect
.Top()+1 );
629 if (aGeo
.nRotationAngle
!=0) {
630 Point
aTmpPt(aAnkRect
.TopLeft());
631 RotatePoint(aTmpPt
,aRotateRef
,aGeo
.nSin
,aGeo
.nCos
);
632 aTmpPt
-=aAnkRect
.TopLeft();
633 aAnkRect
.Move(aTmpPt
.X(),aTmpPt
.Y());
635 rAnchorRect
=aAnkRect
;
638 void SdrTextObj::TakeTextRect( SdrOutliner
& rOutliner
, tools::Rectangle
& rTextRect
, bool bNoEditText
,
639 tools::Rectangle
* pAnchorRect
, bool bLineWidth
) const
641 tools::Rectangle aAnkRect
; // the rectangle in which we anchor
642 TakeTextAnchorRect(aAnkRect
);
643 SdrTextVertAdjust eVAdj
=GetTextVerticalAdjust();
644 SdrTextHorzAdjust eHAdj
=GetTextHorizontalAdjust();
645 SdrTextAniKind eAniKind
=GetTextAniKind();
646 SdrTextAniDirection eAniDirection
=GetTextAniDirection();
648 bool bFitToSize(IsFitToSize());
649 bool bContourFrame
=IsContourTextFrame();
651 bool bFrame
=IsTextFrame();
652 EEControlBits nStat0
=rOutliner
.GetControlWord();
656 rOutliner
.SetControlWord(nStat0
|EEControlBits::AUTOPAGESIZE
);
657 rOutliner
.SetMinAutoPaperSize(aNullSize
);
658 rOutliner
.SetMaxAutoPaperSize(Size(1000000,1000000));
661 if (!bFitToSize
&& !bContourFrame
)
663 long nAnkWdt
=aAnkRect
.GetWidth();
664 long nAnkHgt
=aAnkRect
.GetHeight();
670 bool bInEditMode
= IsInEditMode();
672 if (!bInEditMode
&& (eAniKind
==SdrTextAniKind::Scroll
|| eAniKind
==SdrTextAniKind::Alternate
|| eAniKind
==SdrTextAniKind::Slide
))
674 // unlimited paper size for ticker text
675 if (eAniDirection
==SdrTextAniDirection::Left
|| eAniDirection
==SdrTextAniDirection::Right
) nWdt
=1000000;
676 if (eAniDirection
==SdrTextAniDirection::Up
|| eAniDirection
==SdrTextAniDirection::Down
) nHgt
=1000000;
679 bool bChainedFrame
= IsChainable();
680 // Might be required for overflow check working: do limit height to frame if box is chainable.
681 if (!bChainedFrame
) {
682 // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
684 if(IsVerticalWriting())
694 rOutliner
.SetMaxAutoPaperSize(Size(nWdt
,nHgt
));
697 // New try with _BLOCK for hor and ver after completely
698 // supporting full width for vertical text.
699 if(SDRTEXTHORZADJUST_BLOCK
== eHAdj
&& !IsVerticalWriting())
701 rOutliner
.SetMinAutoPaperSize(Size(nAnkWdt
, 0));
704 if(SDRTEXTVERTADJUST_BLOCK
== eVAdj
&& IsVerticalWriting())
706 rOutliner
.SetMinAutoPaperSize(Size(0, nAnkHgt
));
710 rOutliner
.SetPaperSize(aNullSize
);
712 ImpSetContourPolygon( rOutliner
, aAnkRect
, bLineWidth
);
714 // put text into the outliner, if available from the edit outliner
715 SdrText
* pText
= getActiveText();
716 OutlinerParaObject
* pOutlinerParaObject
= pText
? pText
->GetOutlinerParaObject() : nullptr;
717 OutlinerParaObject
* pPara
= (pEdtOutl
&& !bNoEditText
) ? pEdtOutl
->CreateParaObject().release() : pOutlinerParaObject
;
721 const bool bHitTest(&getSdrModelFromSdrObject().GetHitTestOutliner() == &rOutliner
);
722 const SdrTextObj
* pTestObj
= rOutliner
.GetTextObj();
724 if( !pTestObj
|| !bHitTest
|| pTestObj
!= this ||
725 pTestObj
->GetOutlinerParaObject() != pOutlinerParaObject
)
727 if( bHitTest
) // #i33696# take back fix #i27510#
729 rOutliner
.SetTextObj( this );
730 rOutliner
.SetFixedCellHeight(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT
).GetValue());
733 rOutliner
.SetUpdateMode(true);
734 rOutliner
.SetText(*pPara
);
739 rOutliner
.SetTextObj( nullptr );
742 if (pEdtOutl
&& !bNoEditText
&& pPara
)
745 rOutliner
.SetUpdateMode(true);
746 rOutliner
.SetControlWord(nStat0
);
749 pText
->CheckPortionInfo(rOutliner
);
751 Point
aTextPos(aAnkRect
.TopLeft());
752 Size
aTextSiz(rOutliner
.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
754 // For draw objects containing text correct hor/ver alignment if text is bigger
755 // than the object itself. Without that correction, the text would always be
756 // formatted to the left edge (or top edge when vertical) of the draw object.
759 if(aAnkRect
.GetWidth() < aTextSiz
.Width() && !IsVerticalWriting())
761 // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
762 // else the alignment is wanted.
763 if(SDRTEXTHORZADJUST_BLOCK
== eHAdj
)
765 eHAdj
= SDRTEXTHORZADJUST_CENTER
;
769 if(aAnkRect
.GetHeight() < aTextSiz
.Height() && IsVerticalWriting())
771 // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
772 // else the alignment is wanted.
773 if(SDRTEXTVERTADJUST_BLOCK
== eVAdj
)
775 eVAdj
= SDRTEXTVERTADJUST_CENTER
;
780 if (eHAdj
==SDRTEXTHORZADJUST_CENTER
|| eHAdj
==SDRTEXTHORZADJUST_RIGHT
)
782 long nFreeWdt
=aAnkRect
.GetWidth()-aTextSiz
.Width();
783 if (eHAdj
==SDRTEXTHORZADJUST_CENTER
)
784 aTextPos
.AdjustX(nFreeWdt
/2 );
785 if (eHAdj
==SDRTEXTHORZADJUST_RIGHT
)
786 aTextPos
.AdjustX(nFreeWdt
);
788 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
|| eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
790 long nFreeHgt
=aAnkRect
.GetHeight()-aTextSiz
.Height();
791 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
)
792 aTextPos
.AdjustY(nFreeHgt
/2 );
793 if (eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
794 aTextPos
.AdjustY(nFreeHgt
);
796 if (aGeo
.nRotationAngle
!=0)
797 RotatePoint(aTextPos
,aAnkRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
800 *pAnchorRect
=aAnkRect
;
802 // rTextRect might not be correct in some cases at ContourFrame
803 rTextRect
=tools::Rectangle(aTextPos
,aTextSiz
);
808 bool SdrTextObj::CanCreateEditOutlinerParaObject() const
810 if( HasTextImpl( pEdtOutl
) )
812 return pEdtOutl
->GetParagraphCount() > 0;
817 std::unique_ptr
<OutlinerParaObject
> SdrTextObj::CreateEditOutlinerParaObject() const
819 std::unique_ptr
<OutlinerParaObject
> pPara
;
820 if( HasTextImpl( pEdtOutl
) )
822 sal_Int32 nParaCount
= pEdtOutl
->GetParagraphCount();
823 pPara
= pEdtOutl
->CreateParaObject(0, nParaCount
);
828 void SdrTextObj::ImpSetCharStretching(SdrOutliner
& rOutliner
, const Size
& rTextSize
, const Size
& rShapeSize
, Fraction
& rFitXCorrection
)
830 OutputDevice
* pOut
= rOutliner
.GetRefDevice();
831 bool bNoStretching(false);
833 if(pOut
&& pOut
->GetOutDevType() == OUTDEV_PRINTER
)
835 // check whether CharStretching is possible at all
836 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
837 OUString
aTestString(u
'J');
839 if(pMtf
&& (!pMtf
->IsRecord() || pMtf
->IsPause()))
845 vcl::Font
aOriginalFont(pOut
->GetFont());
846 vcl::Font
aTmpFont( OutputDevice::GetDefaultFont( DefaultFontType::SERIF
, LANGUAGE_SYSTEM
, GetDefaultFontFlags::OnlyOne
) );
848 aTmpFont
.SetFontSize(Size(0,100));
849 pOut
->SetFont(aTmpFont
);
850 Size
aSize1(pOut
->GetTextWidth(aTestString
), pOut
->GetTextHeight());
851 aTmpFont
.SetFontSize(Size(800,100));
852 pOut
->SetFont(aTmpFont
);
853 Size
aSize2(pOut
->GetTextWidth(aTestString
), pOut
->GetTextHeight());
854 pOut
->SetFont(aOriginalFont
);
859 bNoStretching
= (aSize1
== aSize2
);
862 // Windows zooms the font proportionally when using Size(100,500),
863 // we don't like that.
864 if(aSize2
.Height() >= aSize1
.Height() * 2)
866 bNoStretching
= true;
870 unsigned nLoopCount
=0;
871 bool bNoMoreLoop
= false;
872 long nXDiff0
=0x7FFFFFFF;
873 long nWantWdt
=rShapeSize
.Width();
874 long nIsWdt
=rTextSize
.Width();
875 if (nIsWdt
==0) nIsWdt
=1;
877 long nWantHgt
=rShapeSize
.Height();
878 long nIsHgt
=rTextSize
.Height();
879 if (nIsHgt
==0) nIsHgt
=1;
881 long nXTolPl
=nWantWdt
/100; // tolerance: +1%
882 long nXTolMi
=nWantWdt
/25; // tolerance: -4%
883 long nXCorr
=nWantWdt
/20; // correction scale: 5%
885 long nX
=(nWantWdt
*100) /nIsWdt
; // calculate X stretching
886 long nY
=(nWantHgt
*100) /nIsHgt
; // calculate Y stretching
888 if (bNoStretching
) { // might only be possible proportionally
889 if (nX
>nY
) { nX
=nY
; bChkX
=false; }
893 while (nLoopCount
<5 && !bNoMoreLoop
) {
895 if (nX
<1) { nX
=1; bNoMoreLoop
= true; }
896 if (nX
>65535) { nX
=65535; bNoMoreLoop
= true; }
899 if (nY
<1) { nY
=1; bNoMoreLoop
= true; }
900 if (nY
>65535) { nY
=65535; bNoMoreLoop
= true; }
902 // exception, there is no text yet (horizontal case)
909 // exception, there is no text yet (vertical case)
916 rOutliner
.SetGlobalCharStretching(static_cast<sal_uInt16
>(nX
),static_cast<sal_uInt16
>(nY
));
918 Size
aSiz(rOutliner
.CalcTextSize());
919 long nXDiff
=aSiz
.Width()-nWantWdt
;
920 rFitXCorrection
=Fraction(nWantWdt
,aSiz
.Width());
921 if (((nXDiff
>=nXTolMi
|| !bChkX
) && nXDiff
<=nXTolPl
) || nXDiff
==nXDiff0
) {
924 // correct stretching factors
926 long nDiv
=aSiz
.Width();
927 if (std::abs(nXDiff
)<=2*nXCorr
) {
928 if (nMul
>nDiv
) nDiv
+=(nMul
-nDiv
)/2; // but only add half of what we calculated,
929 else nMul
+=(nDiv
-nMul
)/2; // because the EditEngine calculates wrongly later on
932 if (bNoStretching
) nY
=nX
;
938 OUString
SdrTextObj::TakeObjNameSingul() const
944 case OBJ_OUTLINETEXT
:
946 aStr
= SvxResId(STR_ObjNameSingulOUTLINETEXT
);
952 aStr
= SvxResId(STR_ObjNameSingulTITLETEXT
);
959 aStr
= SvxResId(STR_ObjNameSingulTEXTLNK
);
961 aStr
= SvxResId(STR_ObjNameSingulTEXT
);
966 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
967 if(pOutlinerParaObject
&& eTextKind
!= OBJ_OUTLINETEXT
)
969 // shouldn't currently cause any problems at OUTLINETEXT
970 OUString
aStr2(comphelper::string::stripStart(pOutlinerParaObject
->GetTextObject().GetText(0), ' '));
972 // avoid non expanded text portions in object name
973 // (second condition is new)
974 if(!aStr2
.isEmpty() && aStr2
.indexOf(u
'\x00FF') == -1)
976 // space between ResStr and content text
979 if(aStr2
.getLength() > 10)
981 aStr2
= aStr2
.copy(0, 8) + "...";
984 aStr
+= aStr2
+ "\'";
988 OUStringBuffer
sName(aStr
);
990 OUString
aName(GetName());
991 if (!aName
.isEmpty())
999 return sName
.makeStringAndClear();
1002 OUString
SdrTextObj::TakeObjNamePlural() const
1005 switch (eTextKind
) {
1006 case OBJ_OUTLINETEXT
: sName
=SvxResId(STR_ObjNamePluralOUTLINETEXT
); break;
1007 case OBJ_TITLETEXT
: sName
=SvxResId(STR_ObjNamePluralTITLETEXT
); break;
1009 if (IsLinkedText()) {
1010 sName
=SvxResId(STR_ObjNamePluralTEXTLNK
);
1012 sName
=SvxResId(STR_ObjNamePluralTEXT
);
1019 SdrTextObj
* SdrTextObj::CloneSdrObject(SdrModel
& rTargetModel
) const
1021 return CloneHelper
< SdrTextObj
>(rTargetModel
);
1024 SdrTextObj
& SdrTextObj::operator=(const SdrTextObj
& rObj
)
1029 // call parent. tdf#116979: use the correct parent class
1030 SdrAttrObj::operator=(rObj
);
1032 maRect
= rObj
.maRect
;
1034 eTextKind
=rObj
.eTextKind
;
1035 bTextFrame
=rObj
.bTextFrame
;
1036 aTextSize
=rObj
.aTextSize
;
1037 bTextSizeDirty
=rObj
.bTextSizeDirty
;
1039 // Not all of the necessary parameters were copied yet.
1040 bNoShear
= rObj
.bNoShear
;
1041 bDisableAutoWidthOnDragging
= rObj
.bDisableAutoWidthOnDragging
;
1042 SdrText
* pText
= getActiveText();
1044 if( pText
&& rObj
.HasText() )
1046 // before pNewOutlinerParaObject was created the same, but
1047 // set at mpText (outside this scope), but mpText might be
1048 // empty (this operator== seems not prepared for MultiText
1049 // objects). In the current form it makes only sense to
1050 // create locally and use locally on a known existing SdrText
1051 const Outliner
* pEO
=rObj
.pEdtOutl
;
1052 std::unique_ptr
<OutlinerParaObject
> pNewOutlinerParaObject
;
1056 pNewOutlinerParaObject
= pEO
->CreateParaObject();
1058 else if (nullptr != rObj
.getActiveText()->GetOutlinerParaObject())
1060 pNewOutlinerParaObject
.reset( new OutlinerParaObject(*rObj
.getActiveText()->GetOutlinerParaObject()) );
1063 pText
->SetOutlinerParaObject( std::move(pNewOutlinerParaObject
) );
1066 ImpSetTextStyleSheetListeners();
1070 basegfx::B2DPolyPolygon
SdrTextObj::TakeXorPoly() const
1072 tools::Polygon
aPol(maRect
);
1073 if (aGeo
.nShearAngle
!=0) ShearPoly(aPol
,maRect
.TopLeft(),aGeo
.nTan
);
1074 if (aGeo
.nRotationAngle
!=0) RotatePoly(aPol
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
1076 basegfx::B2DPolyPolygon aRetval
;
1077 aRetval
.append(aPol
.getB2DPolygon());
1081 basegfx::B2DPolyPolygon
SdrTextObj::TakeContour() const
1083 basegfx::B2DPolyPolygon
aRetval(SdrAttrObj::TakeContour());
1085 // and now add the BoundRect of the text, if necessary
1086 if ( GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1088 // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1089 // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1091 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
1093 tools::Rectangle aAnchor2
;
1094 tools::Rectangle aR
;
1095 TakeTextRect(rOutliner
,aR
,false,&aAnchor2
);
1097 bool bFitToSize(IsFitToSize());
1098 if (bFitToSize
) aR
=aAnchor2
;
1099 tools::Polygon
aPol(aR
);
1100 if (aGeo
.nRotationAngle
!=0) RotatePoly(aPol
,aR
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
1102 aRetval
.append(aPol
.getB2DPolygon());
1108 void SdrTextObj::RecalcSnapRect()
1110 if (aGeo
.nRotationAngle
!=0 || aGeo
.nShearAngle
!=0)
1112 tools::Polygon
aPol(maRect
);
1113 if (aGeo
.nShearAngle
!=0) ShearPoly(aPol
,maRect
.TopLeft(),aGeo
.nTan
);
1114 if (aGeo
.nRotationAngle
!=0) RotatePoly(aPol
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
1115 maSnapRect
=aPol
.GetBoundRect();
1117 maSnapRect
= maRect
;
1121 sal_uInt32
SdrTextObj::GetSnapPointCount() const
1126 Point
SdrTextObj::GetSnapPoint(sal_uInt32 i
) const
1130 case 0: aP
=maRect
.TopLeft(); break;
1131 case 1: aP
=maRect
.TopRight(); break;
1132 case 2: aP
=maRect
.BottomLeft(); break;
1133 case 3: aP
=maRect
.BottomRight(); break;
1134 default: aP
=maRect
.Center(); break;
1136 if (aGeo
.nShearAngle
!=0) ShearPoint(aP
,maRect
.TopLeft(),aGeo
.nTan
);
1137 if (aGeo
.nRotationAngle
!=0) RotatePoint(aP
,maRect
.TopLeft(),aGeo
.nSin
,aGeo
.nCos
);
1141 // Extracted from ImpGetDrawOutliner()
1142 void SdrTextObj::ImpInitDrawOutliner( SdrOutliner
& rOutl
) const
1144 rOutl
.SetUpdateMode(false);
1145 OutlinerMode nOutlinerMode
= OutlinerMode::OutlineObject
;
1146 if ( !IsOutlText() )
1147 nOutlinerMode
= OutlinerMode::TextObject
;
1148 rOutl
.Init( nOutlinerMode
);
1150 rOutl
.SetGlobalCharStretching();
1151 EEControlBits nStat
=rOutl
.GetControlWord();
1152 nStat
&= ~EEControlBits(EEControlBits::STRETCHING
|EEControlBits::AUTOPAGESIZE
);
1153 rOutl
.SetControlWord(nStat
);
1154 Size
aMaxSize(100000,100000);
1155 rOutl
.SetMinAutoPaperSize(Size());
1156 rOutl
.SetMaxAutoPaperSize(aMaxSize
);
1157 rOutl
.SetPaperSize(aMaxSize
);
1158 rOutl
.ClearPolygon();
1161 SdrOutliner
& SdrTextObj::ImpGetDrawOutliner() const
1163 SdrOutliner
& rOutl(getSdrModelFromSdrObject().GetDrawOutliner(this));
1165 // Code extracted to ImpInitDrawOutliner()
1166 ImpInitDrawOutliner( rOutl
);
1171 // Extracted from Paint()
1172 void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame
,
1173 SdrOutliner
& rOutliner
,
1174 tools::Rectangle
& rTextRect
,
1175 tools::Rectangle
& rAnchorRect
,
1176 tools::Rectangle
& rPaintRect
,
1177 Fraction
& rFitXCorrection
) const
1181 // FitToSize can't be used together with ContourFrame for now
1182 if (IsFitToSize() || IsAutoFit())
1184 EEControlBits nStat
=rOutliner
.GetControlWord();
1185 nStat
|=EEControlBits::STRETCHING
|EEControlBits::AUTOPAGESIZE
;
1186 rOutliner
.SetControlWord(nStat
);
1189 rOutliner
.SetFixedCellHeight(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT
).GetValue());
1190 TakeTextRect(rOutliner
, rTextRect
, false, &rAnchorRect
);
1191 rPaintRect
= rTextRect
;
1195 // FitToSize can't be used together with ContourFrame for now
1198 ImpSetCharStretching(rOutliner
,rTextRect
.GetSize(),rAnchorRect
.GetSize(),rFitXCorrection
);
1199 rPaintRect
=rAnchorRect
;
1201 else if (IsAutoFit())
1203 ImpAutoFitText(rOutliner
);
1208 double SdrTextObj::GetFontScaleY() const
1210 SdrText
* pText
= getActiveText();
1211 if (pText
== nullptr || !pText
->GetOutlinerParaObject())
1214 SdrOutliner
& rOutliner
= ImpGetDrawOutliner();
1215 const Size aShapeSize
= GetSnapRect().GetSize();
1216 const Size
aSize(aShapeSize
.Width() - GetTextLeftDistance() - GetTextRightDistance(),
1217 aShapeSize
.Height() - GetTextUpperDistance() - GetTextLowerDistance());
1219 rOutliner
.SetPaperSize(aSize
);
1220 rOutliner
.SetUpdateMode(true);
1221 rOutliner
.SetText(*pText
->GetOutlinerParaObject());
1222 bool bIsVerticalWriting
= IsVerticalWriting();
1224 // Algorithm from SdrTextObj::ImpAutoFitText
1226 sal_uInt16 nMinStretchX
= 0, nMinStretchY
= 0;
1227 sal_uInt16 nCurrStretchX
= 100, nCurrStretchY
= 100;
1228 sal_uInt16 aOldStretchXVals
[] = { 0,0,0 };
1229 const size_t aStretchArySize
= SAL_N_ELEMENTS(aOldStretchXVals
);
1230 for (unsigned int i
= 0; i
<aStretchArySize
; ++i
)
1232 const Size aCurrTextSize
= rOutliner
.CalcTextSizeNTP();
1233 double fFactor(1.0);
1234 if (bIsVerticalWriting
)
1236 if (aCurrTextSize
.Width() != 0)
1238 fFactor
= double(aSize
.Width()) / aCurrTextSize
.Width();
1241 else if (aCurrTextSize
.Height() != 0)
1243 fFactor
= double(aSize
.Height()) / aCurrTextSize
.Height();
1245 fFactor
= std::sqrt(fFactor
);
1247 rOutliner
.GetGlobalCharStretching(nCurrStretchX
, nCurrStretchY
);
1251 nMinStretchX
= std::max(nMinStretchX
, nCurrStretchX
);
1252 nMinStretchY
= std::max(nMinStretchY
, nCurrStretchY
);
1255 aOldStretchXVals
[i
] = nCurrStretchX
;
1256 if (std::find(aOldStretchXVals
, aOldStretchXVals
+ i
, nCurrStretchX
) != aOldStretchXVals
+ i
)
1257 break; // same value already attained once; algo is looping, exit
1259 if (fFactor
< 1.0 || nCurrStretchX
!= 100)
1261 nCurrStretchX
= sal::static_int_cast
<sal_uInt16
>(nCurrStretchX
*fFactor
);
1262 nCurrStretchY
= sal::static_int_cast
<sal_uInt16
>(nCurrStretchY
*fFactor
);
1263 rOutliner
.SetGlobalCharStretching(std::min(sal_uInt16(100), nCurrStretchX
),
1264 std::min(sal_uInt16(100), nCurrStretchY
));
1268 return std::min(sal_uInt16(100), nCurrStretchY
) / 100.0;
1271 void SdrTextObj::ImpAutoFitText( SdrOutliner
& rOutliner
) const
1273 const Size aShapeSize
=GetSnapRect().GetSize();
1274 ImpAutoFitText( rOutliner
,
1275 Size(aShapeSize
.Width()-GetTextLeftDistance()-GetTextRightDistance(),
1276 aShapeSize
.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
1277 IsVerticalWriting() );
1280 void SdrTextObj::ImpAutoFitText( SdrOutliner
& rOutliner
, const Size
& rTextSize
, bool bIsVerticalWriting
)
1282 // EditEngine formatting is unstable enough for
1283 // line-breaking text that we need some more samples
1285 // loop early-exits if we detect an already attained value
1286 sal_uInt16 nMinStretchX
=0, nMinStretchY
=0;
1287 sal_uInt16 aOldStretchXVals
[]={0,0,0,0,0,0,0,0,0,0};
1288 const size_t aStretchArySize
=SAL_N_ELEMENTS(aOldStretchXVals
);
1289 for(unsigned int i
=0; i
<aStretchArySize
; ++i
)
1291 const Size aCurrTextSize
= rOutliner
.CalcTextSizeNTP();
1292 double fFactor(1.0);
1293 if( bIsVerticalWriting
)
1295 if (aCurrTextSize
.Width() != 0)
1297 fFactor
= double(rTextSize
.Width())/aCurrTextSize
.Width();
1300 else if (aCurrTextSize
.Height() != 0)
1302 fFactor
= double(rTextSize
.Height())/aCurrTextSize
.Height();
1304 // fFactor scales in both x and y directions
1305 // - this is fine for bulleted words
1306 // - but it scales too much for a long paragraph
1307 // - taking sqrt scales long paragraphs the best
1308 // - bulleted words will have to go through more iterations
1309 fFactor
= std::sqrt(fFactor
);
1311 sal_uInt16 nCurrStretchX
, nCurrStretchY
;
1312 rOutliner
.GetGlobalCharStretching(nCurrStretchX
, nCurrStretchY
);
1314 if (fFactor
>= 1.0 )
1316 // resulting text area fits into available shape rect -
1317 // err on the larger stretching, to optimally fill area
1318 nMinStretchX
= std::max(nMinStretchX
,nCurrStretchX
);
1319 nMinStretchY
= std::max(nMinStretchY
,nCurrStretchY
);
1322 aOldStretchXVals
[i
] = nCurrStretchX
;
1323 if( std::find(aOldStretchXVals
, aOldStretchXVals
+i
, nCurrStretchX
) != aOldStretchXVals
+i
)
1324 break; // same value already attained once; algo is looping, exit
1326 if (fFactor
< 1.0 || nCurrStretchX
!= 100)
1328 nCurrStretchX
= sal::static_int_cast
<sal_uInt16
>(nCurrStretchX
*fFactor
);
1329 nCurrStretchY
= sal::static_int_cast
<sal_uInt16
>(nCurrStretchY
*fFactor
);
1330 rOutliner
.SetGlobalCharStretching(std::min(sal_uInt16(100),nCurrStretchX
),
1331 std::min(sal_uInt16(100),nCurrStretchY
));
1332 SAL_INFO("svx", "zoom is " << nCurrStretchX
);
1336 SAL_INFO("svx", "final zoom is " << nMinStretchX
);
1337 rOutliner
.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX
),
1338 std::min(sal_uInt16(100),nMinStretchY
));
1341 void SdrTextObj::SetupOutlinerFormatting( SdrOutliner
& rOutl
, tools::Rectangle
& rPaintRect
) const
1343 ImpInitDrawOutliner( rOutl
);
1344 UpdateOutlinerFormatting( rOutl
, rPaintRect
);
1347 void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner
& rOutl
, tools::Rectangle
& rPaintRect
) const
1349 tools::Rectangle aTextRect
;
1350 tools::Rectangle aAnchorRect
;
1351 Fraction
aFitXCorrection(1,1);
1353 const bool bContourFrame(IsContourTextFrame());
1354 const MapMode
aMapMode(
1355 getSdrModelFromSdrObject().GetScaleUnit(),
1357 getSdrModelFromSdrObject().GetScaleFraction(),
1358 getSdrModelFromSdrObject().GetScaleFraction());
1360 rOutl
.SetRefMapMode(aMapMode
);
1361 ImpSetupDrawOutlinerForPaint(
1371 OutlinerParaObject
* SdrTextObj::GetOutlinerParaObject() const
1373 SdrText
* pText
= getActiveText();
1375 return pText
->GetOutlinerParaObject();
1380 void SdrTextObj::NbcSetOutlinerParaObject(std::unique_ptr
<OutlinerParaObject
> pTextObject
)
1382 NbcSetOutlinerParaObjectForText( std::move(pTextObject
), getActiveText() );
1385 void SdrTextObj::NbcSetOutlinerParaObjectForText( std::unique_ptr
<OutlinerParaObject
> pTextObject
, SdrText
* pText
)
1388 pText
->SetOutlinerParaObject( std::move(pTextObject
) );
1390 if (pText
&& pText
->GetOutlinerParaObject())
1392 SvxWritingModeItem
aWritingMode(pText
->GetOutlinerParaObject()->IsVertical() && pText
->GetOutlinerParaObject()->IsTopToBottom()
1393 ? css::text::WritingMode_TB_RL
1394 : css::text::WritingMode_LR_TB
,
1395 SDRATTR_TEXTDIRECTION
);
1396 GetProperties().SetObjectItemDirect(aWritingMode
);
1400 if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth()))
1401 { // adapt text frame!
1402 NbcAdjustTextFrameWidthAndHeight();
1406 // the SnapRect keeps its size
1407 SetRectsDirty(true);
1410 // always invalidate BoundRect on change
1411 SetBoundRectDirty();
1414 ImpSetTextStyleSheetListeners();
1417 void SdrTextObj::NbcReformatText()
1419 SdrText
* pText
= getActiveText();
1420 if( pText
&& pText
->GetOutlinerParaObject() )
1422 pText
->ReformatText();
1425 NbcAdjustTextFrameWidthAndHeight();
1429 // the SnapRect keeps its size
1430 SetBoundRectDirty();
1431 SetRectsDirty(true);
1436 // Necessary here since we have no compare operator at the outliner
1437 // para object which may detect changes regarding the combination
1438 // of outliner para data and configuration (e.g., change of
1439 // formatting of text numerals)
1440 GetViewContact().flushViewObjectContacts(false);
1444 SdrObjGeoData
* SdrTextObj::NewGeoData() const
1446 return new SdrTextObjGeoData
;
1449 void SdrTextObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
1451 SdrAttrObj::SaveGeoData(rGeo
);
1452 SdrTextObjGeoData
& rTGeo
=static_cast<SdrTextObjGeoData
&>(rGeo
);
1453 rTGeo
.aRect
= maRect
;
1457 void SdrTextObj::RestGeoData(const SdrObjGeoData
& rGeo
)
1458 { // RectsDirty is called by SdrObject
1459 SdrAttrObj::RestGeoData(rGeo
);
1460 const SdrTextObjGeoData
& rTGeo
=static_cast<const SdrTextObjGeoData
&>(rGeo
);
1461 NbcSetLogicRect(rTGeo
.aRect
);
1466 drawing::TextFitToSizeType
SdrTextObj::GetFitToSize() const
1468 drawing::TextFitToSizeType eType
= drawing::TextFitToSizeType_NONE
;
1470 if(!IsAutoGrowWidth())
1471 eType
= GetObjectItem(SDRATTR_TEXT_FITTOSIZE
).GetValue();
1476 const tools::Rectangle
& SdrTextObj::GetGeoRect() const
1481 void SdrTextObj::ForceOutlinerParaObject()
1483 SdrText
* pText
= getActiveText();
1484 if( pText
&& (pText
->GetOutlinerParaObject() == nullptr) )
1486 OutlinerMode nOutlMode
= OutlinerMode::TextObject
;
1487 if( IsTextFrame() && eTextKind
== OBJ_OUTLINETEXT
)
1488 nOutlMode
= OutlinerMode::OutlineObject
;
1490 pText
->ForceOutlinerParaObject( nOutlMode
);
1494 TextChain
*SdrTextObj::GetTextChain() const
1496 //if (!IsChainable())
1499 return getSdrModelFromSdrObject().GetTextChain();
1502 bool SdrTextObj::IsVerticalWriting() const
1506 return pEdtOutl
->IsVertical();
1509 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
1510 if(pOutlinerParaObject
)
1512 return pOutlinerParaObject
->IsVertical();
1518 void SdrTextObj::SetVerticalWriting(bool bVertical
)
1520 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
1522 if( !pOutlinerParaObject
&& bVertical
)
1524 // we only need to force an outliner para object if the default of
1525 // horizontal text is changed
1526 ForceOutlinerParaObject();
1527 pOutlinerParaObject
= GetOutlinerParaObject();
1530 if (!pOutlinerParaObject
||
1531 (pOutlinerParaObject
->IsVertical() == bVertical
))
1534 // get item settings
1535 const SfxItemSet
& rSet
= GetObjectItemSet();
1536 bool bAutoGrowWidth
= rSet
.Get(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue();
1537 bool bAutoGrowHeight
= rSet
.Get(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
1539 // Also exchange hor/ver adjust items
1540 SdrTextHorzAdjust eHorz
= rSet
.Get(SDRATTR_TEXT_HORZADJUST
).GetValue();
1541 SdrTextVertAdjust eVert
= rSet
.Get(SDRATTR_TEXT_VERTADJUST
).GetValue();
1543 // rescue object size
1544 tools::Rectangle aObjectRect
= GetSnapRect();
1546 // prepare ItemSet to set exchanged width and height items
1547 SfxItemSet
aNewSet(*rSet
.GetPool(),
1548 svl::Items
<SDRATTR_TEXT_AUTOGROWHEIGHT
, SDRATTR_TEXT_AUTOGROWHEIGHT
,
1549 // Expanded item ranges to also support hor and ver adjust.
1550 SDRATTR_TEXT_VERTADJUST
, SDRATTR_TEXT_VERTADJUST
,
1551 SDRATTR_TEXT_AUTOGROWWIDTH
, SDRATTR_TEXT_HORZADJUST
>{});
1554 aNewSet
.Put(makeSdrTextAutoGrowWidthItem(bAutoGrowHeight
));
1555 aNewSet
.Put(makeSdrTextAutoGrowHeightItem(bAutoGrowWidth
));
1557 // Exchange horz and vert adjusts
1560 case SDRTEXTVERTADJUST_TOP
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
)); break;
1561 case SDRTEXTVERTADJUST_CENTER
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER
)); break;
1562 case SDRTEXTVERTADJUST_BOTTOM
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT
)); break;
1563 case SDRTEXTVERTADJUST_BLOCK
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK
)); break;
1567 case SDRTEXTHORZADJUST_LEFT
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM
)); break;
1568 case SDRTEXTHORZADJUST_CENTER
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
)); break;
1569 case SDRTEXTHORZADJUST_RIGHT
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP
)); break;
1570 case SDRTEXTHORZADJUST_BLOCK
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK
)); break;
1573 SetObjectItemSet(aNewSet
);
1575 pOutlinerParaObject
= GetOutlinerParaObject();
1576 if (pOutlinerParaObject
)
1578 // set ParaObject orientation accordingly
1579 pOutlinerParaObject
->SetVertical(bVertical
);
1582 // restore object size
1583 SetSnapRect(aObjectRect
);
1586 // transformation interface for StarOfficeAPI. This implements support for
1587 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1588 // moment it contains a shearX, rotation and translation, but for setting all linear
1589 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1592 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1593 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1594 bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
1596 // get turn and shear
1597 double fRotate
= basegfx::deg2rad(aGeo
.nRotationAngle
/ 100.0);
1598 double fShearX
= basegfx::deg2rad(aGeo
.nShearAngle
/ 100.0);
1600 // get aRect, this is the unrotated snaprect
1601 tools::Rectangle
aRectangle(maRect
);
1603 // fill other values
1604 basegfx::B2DTuple
aScale(aRectangle
.GetWidth(), aRectangle
.GetHeight());
1605 basegfx::B2DTuple
aTranslate(aRectangle
.Left(), aRectangle
.Top());
1607 // position maybe relative to anchorpos, convert
1608 if( getSdrModelFromSdrObject().IsWriter() )
1610 if(GetAnchorPos().X() || GetAnchorPos().Y())
1612 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1617 rMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
1619 basegfx::fTools::equalZero(fShearX
) ? 0.0 : tan(fShearX
),
1620 basegfx::fTools::equalZero(fRotate
) ? 0.0 : -fRotate
,
1626 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1627 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1628 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1629 void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
1632 basegfx::B2DTuple aScale
;
1633 basegfx::B2DTuple aTranslate
;
1634 double fRotate(0.0);
1635 double fShearX(0.0);
1636 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1639 bool bFlipX
= aScale
.getX() < 0.0,
1640 bFlipY
= aScale
.getY() < 0.0;
1643 aScale
.setX(fabs(aScale
.getX()));
1647 aScale
.setY(fabs(aScale
.getY()));
1650 // reset object shear and rotations
1651 aGeo
.nRotationAngle
= 0;
1652 aGeo
.RecalcSinCos();
1653 aGeo
.nShearAngle
= 0;
1656 // if anchor is used, make position relative to it
1657 if( getSdrModelFromSdrObject().IsWriter() )
1659 if(GetAnchorPos().X() || GetAnchorPos().Y())
1661 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1665 // build and set BaseRect (use scale)
1666 Size
aSize(FRound(aScale
.getX()), FRound(aScale
.getY()));
1667 tools::Rectangle
aBaseRect(Point(), aSize
);
1668 SetSnapRect(aBaseRect
);
1673 Mirror(Point(), Point(0, 1));
1677 Mirror(Point(), Point(1, 0));
1681 if(!basegfx::fTools::equalZero(fShearX
))
1684 aGeoStat
.nShearAngle
= FRound(basegfx::rad2deg(atan(fShearX
)) * 100.0);
1685 aGeoStat
.RecalcTan();
1686 Shear(Point(), aGeoStat
.nShearAngle
, aGeoStat
.nTan
, false);
1690 if(!basegfx::fTools::equalZero(fRotate
))
1695 // fRotate is matematically correct, but aGeoStat.nRotationAngle is
1696 // mirrored -> mirror value here
1697 aGeoStat
.nRotationAngle
= NormAngle36000(FRound(-fRotate
/ F_PI18000
));
1698 aGeoStat
.RecalcSinCos();
1699 Rotate(Point(), aGeoStat
.nRotationAngle
, aGeoStat
.nSin
, aGeoStat
.nCos
);
1703 if(!aTranslate
.equalZero())
1705 Move(Size(FRound(aTranslate
.getX()), FRound(aTranslate
.getY())));
1709 bool SdrTextObj::IsReallyEdited() const
1711 return pEdtOutl
&& pEdtOutl
->IsModified();
1714 // moved inlines here form hxx
1716 long SdrTextObj::GetEckenradius() const
1718 return GetObjectItemSet().Get(SDRATTR_ECKENRADIUS
).GetValue();
1721 long SdrTextObj::GetMinTextFrameHeight() const
1723 return GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT
).GetValue();
1726 long SdrTextObj::GetMaxTextFrameHeight() const
1728 return GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT
).GetValue();
1731 long SdrTextObj::GetMinTextFrameWidth() const
1733 return GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH
).GetValue();
1736 long SdrTextObj::GetMaxTextFrameWidth() const
1738 return GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH
).GetValue();
1741 bool SdrTextObj::IsFontwork() const
1743 return !bTextFrame
// Default is FALSE
1744 && GetObjectItemSet().Get(XATTR_FORMTXTSTYLE
).GetValue() != XFormTextStyle::NONE
;
1747 bool SdrTextObj::IsHideContour() const
1749 return !bTextFrame
// Default is: no, don't HideContour; HideContour not together with TextFrames
1750 && GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM
).GetValue();
1753 bool SdrTextObj::IsContourTextFrame() const
1755 return !bTextFrame
// ContourFrame not together with normal TextFrames
1756 && GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME
).GetValue();
1759 long SdrTextObj::GetTextLeftDistance() const
1761 return GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST
).GetValue();
1764 long SdrTextObj::GetTextRightDistance() const
1766 return GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST
).GetValue();
1769 long SdrTextObj::GetTextUpperDistance() const
1771 return GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST
).GetValue();
1774 long SdrTextObj::GetTextLowerDistance() const
1776 return GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST
).GetValue();
1779 SdrTextAniKind
SdrTextObj::GetTextAniKind() const
1781 return GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND
).GetValue();
1784 SdrTextAniDirection
SdrTextObj::GetTextAniDirection() const
1786 return GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
1789 // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1790 // painting rectangle. Rotation is excluded from the returned values.
1791 GDIMetaFile
* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1792 tools::Rectangle
& rScrollRectangle
, tools::Rectangle
& rPaintRectangle
)
1794 GDIMetaFile
* pRetval
= nullptr;
1795 SdrOutliner
& rOutliner
= ImpGetDrawOutliner();
1796 tools::Rectangle aTextRect
;
1797 tools::Rectangle aAnchorRect
;
1798 tools::Rectangle aPaintRect
;
1799 Fraction
aFitXCorrection(1,1);
1800 bool bContourFrame(IsContourTextFrame());
1802 // get outliner set up. To avoid getting a somehow rotated MetaFile,
1803 // temporarily disable object rotation.
1804 sal_Int32
nAngle(aGeo
.nRotationAngle
);
1805 aGeo
.nRotationAngle
= 0;
1806 ImpSetupDrawOutlinerForPaint( bContourFrame
, rOutliner
, aTextRect
, aAnchorRect
, aPaintRect
, aFitXCorrection
);
1807 aGeo
.nRotationAngle
= nAngle
;
1809 tools::Rectangle
aScrollFrameRect(aPaintRect
);
1810 const SfxItemSet
& rSet
= GetObjectItemSet();
1811 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
1813 if(SdrTextAniDirection::Left
== eDirection
|| SdrTextAniDirection::Right
== eDirection
)
1815 aScrollFrameRect
.SetLeft( aAnchorRect
.Left() );
1816 aScrollFrameRect
.SetRight( aAnchorRect
.Right() );
1819 if(SdrTextAniDirection::Up
== eDirection
|| SdrTextAniDirection::Down
== eDirection
)
1821 aScrollFrameRect
.SetTop( aAnchorRect
.Top() );
1822 aScrollFrameRect
.SetBottom( aAnchorRect
.Bottom() );
1825 // create the MetaFile
1826 pRetval
= new GDIMetaFile
;
1827 ScopedVclPtrInstance
< VirtualDevice
> pBlackHole
;
1828 pBlackHole
->EnableOutput(false);
1829 pRetval
->Record(pBlackHole
);
1830 Point aPaintPos
= aPaintRect
.TopLeft();
1832 rOutliner
.Draw(pBlackHole
, aPaintPos
);
1835 pRetval
->WindStart();
1837 // return PaintRectanglePixel and pRetval;
1838 rScrollRectangle
= aScrollFrameRect
;
1839 rPaintRectangle
= aPaintRect
;
1844 // Access to TextAnimationAllowed flag
1845 bool SdrTextObj::IsAutoFit() const
1847 return GetFitToSize() == drawing::TextFitToSizeType_AUTOFIT
;
1850 bool SdrTextObj::IsFitToSize() const
1852 const drawing::TextFitToSizeType eFit
= GetFitToSize();
1853 return (eFit
== drawing::TextFitToSizeType_PROPORTIONAL
1854 || eFit
== drawing::TextFitToSizeType_ALLLINES
);
1857 void SdrTextObj::SetTextAnimationAllowed(bool bNew
)
1859 if(mbTextAnimationAllowed
!= bNew
)
1861 mbTextAnimationAllowed
= bNew
;
1866 /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1867 void SdrTextObj::onEditOutlinerStatusEvent( EditStatus
* pEditStatus
)
1869 const EditStatusFlags nStat
= pEditStatus
->GetStatusWord();
1870 const bool bGrowX
= bool(nStat
& EditStatusFlags::TEXTWIDTHCHANGED
);
1871 const bool bGrowY
= bool(nStat
& EditStatusFlags::TextHeightChanged
);
1872 if(bTextFrame
&& (bGrowX
|| bGrowY
))
1874 if ((bGrowX
&& IsAutoGrowWidth()) || (bGrowY
&& IsAutoGrowHeight()))
1876 AdjustTextFrameWidthAndHeight();
1878 else if ( (IsAutoFit() || IsFitToSize()) && !mbInDownScale
)
1881 mbInDownScale
= true;
1883 // sucks that we cannot disable paints via
1884 // pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
1885 // formatting as well, then.
1886 ImpAutoFitText(*pEdtOutl
);
1887 mbInDownScale
= false;
1892 /* Begin chaining code */
1894 // XXX: Make it a method somewhere?
1895 static SdrObject
*ImpGetObjByName(SdrObjList
const *pObjList
, OUString
const& aObjName
)
1897 // scan the whole list
1898 size_t nObjCount
= pObjList
->GetObjCount();
1899 for (size_t i
= 0; i
< nObjCount
; i
++) {
1900 SdrObject
*pCurObj
= pObjList
->GetObj(i
);
1902 if (pCurObj
->GetName() == aObjName
) {
1910 // XXX: Make it a (private) method of SdrTextObj
1911 static void ImpUpdateChainLinks(SdrTextObj
*pTextObj
, OUString
const& aNextLinkName
)
1913 // XXX: Current implementation constraints text boxes to be on the same page
1916 if (aNextLinkName
.isEmpty()) {
1917 pTextObj
->SetNextLinkInChain(nullptr);
1921 SdrPage
*pPage(pTextObj
->getSdrPageFromSdrObject());
1923 SdrTextObj
*pNextTextObj
= dynamic_cast< SdrTextObj
* >
1924 (ImpGetObjByName(pPage
, aNextLinkName
));
1925 if (!pNextTextObj
) {
1926 SAL_INFO("svx.chaining", "[CHAINING] Can't find object as next link.");
1930 pTextObj
->SetNextLinkInChain(pNextTextObj
);
1933 bool SdrTextObj::IsChainable() const
1936 const SfxItemSet
& rSet
= GetObjectItemSet();
1937 OUString aNextLinkName
= rSet
.Get(SDRATTR_TEXT_CHAINNEXTNAME
).GetValue();
1939 // Update links if any inconsistency is found
1940 bool bNextLinkUnsetYet
= !aNextLinkName
.isEmpty() && !mpNextInChain
;
1941 bool bInconsistentNextLink
= mpNextInChain
&& mpNextInChain
->GetName() != aNextLinkName
;
1942 // if the link is not set despite there should be one OR if it has changed
1943 if (bNextLinkUnsetYet
|| bInconsistentNextLink
) {
1944 ImpUpdateChainLinks(const_cast<SdrTextObj
*>(this), aNextLinkName
);
1947 return !aNextLinkName
.isEmpty(); // XXX: Should we also check for GetNilChainingEvent? (see old code below)
1950 // Check that no overflow is going on
1951 if (!GetTextChain() || GetTextChain()->GetNilChainingEvent(this))
1956 void SdrTextObj::onChainingEvent()
1961 // Outliner for text transfer
1962 SdrOutliner
&aDrawOutliner
= ImpGetDrawOutliner();
1964 EditingTextChainFlow
aTxtChainFlow(this);
1965 aTxtChainFlow
.CheckForFlowEvents(pEdtOutl
);
1967 if (aTxtChainFlow
.IsOverflow()) {
1968 SAL_INFO("svx.chaining", "[CHAINING] Overflow going on");
1969 // One outliner is for non-overflowing text, the other for overflowing text
1970 // We remove text directly from the editing outliner
1971 aTxtChainFlow
.ExecuteOverflow(pEdtOutl
, &aDrawOutliner
);
1972 } else if (aTxtChainFlow
.IsUnderflow()) {
1973 SAL_INFO("svx.chaining", "[CHAINING] Underflow going on");
1974 // underflow-induced overflow
1975 aTxtChainFlow
.ExecuteUnderflow(&aDrawOutliner
);
1976 bool bIsOverflowFromUnderflow
= aTxtChainFlow
.IsOverflow();
1978 if (bIsOverflowFromUnderflow
) {
1979 SAL_INFO("svx.chaining", "[CHAINING] Overflow going on (underflow induced)");
1980 // prevents infinite loops when setting text for editing outliner
1981 aTxtChainFlow
.ExecuteOverflow(&aDrawOutliner
, &aDrawOutliner
);
1986 SdrTextObj
* SdrTextObj::GetNextLinkInChain() const
1990 return GetTextChain()->GetNextLink(this);
1995 return mpNextInChain
;
1998 void SdrTextObj::SetNextLinkInChain(SdrTextObj
*pNextObj
)
2000 // Basically a doubly linked list implementation
2002 SdrTextObj
*pOldNextObj
= mpNextInChain
;
2004 // Replace next link
2005 mpNextInChain
= pNextObj
;
2006 // Deal with old next link's prev link
2008 pOldNextObj
->mpPrevInChain
= nullptr;
2011 // Deal with new next link's prev link
2012 if (mpNextInChain
) {
2013 // If there is a prev already at all and this is not already the current object
2014 if (mpNextInChain
->mpPrevInChain
&&
2015 mpNextInChain
->mpPrevInChain
!= this)
2016 mpNextInChain
->mpPrevInChain
->mpNextInChain
= nullptr;
2017 mpNextInChain
->mpPrevInChain
= this;
2020 // TODO: Introduce check for circular chains
2024 SdrTextObj
* SdrTextObj::GetPrevLinkInChain() const
2028 return GetTextChain()->GetPrevLink(this);
2033 return mpPrevInChain
;
2036 bool SdrTextObj::GetPreventChainable() const
2038 // Prevent chaining it 1) during dragging && 2) when we are editing next link
2039 return mbIsUnchainableClone
|| (GetNextLinkInChain() && GetNextLinkInChain()->IsInEditMode());
2042 SdrObjectUniquePtr
SdrTextObj::getFullDragClone() const
2044 SdrObjectUniquePtr pClone
= SdrAttrObj::getFullDragClone();
2045 SdrTextObj
*pTextObjClone
= dynamic_cast<SdrTextObj
*>(pClone
.get());
2046 if (pTextObjClone
!= nullptr) {
2047 // Avoid transferring of text for chainable object during dragging
2048 pTextObjClone
->mbIsUnchainableClone
= true;
2054 /* End chaining code */
2056 /** returns the currently active text. */
2057 SdrText
* SdrTextObj::getActiveText() const
2060 return getText( 0 );
2062 return mpText
.get();
2065 /** returns the nth available text. */
2066 SdrText
* SdrTextObj::getText( sal_Int32 nIndex
) const
2071 const_cast< SdrTextObj
* >(this)->mpText
.reset( new SdrText( *const_cast< SdrTextObj
* >(this) ) );
2072 return mpText
.get();
2080 /** returns the number of texts available for this object. */
2081 sal_Int32
SdrTextObj::getTextCount() const
2086 /** changes the current active text */
2087 void SdrTextObj::setActiveText( sal_Int32
/*nIndex*/ )
2091 /** returns the index of the text that contains the given point or -1 */
2092 sal_Int32
SdrTextObj::CheckTextHit(const Point
& /*rPnt*/) const
2097 void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem
& rItem
)
2099 static_cast< sdr::properties::TextProperties
& >(GetProperties()).SetObjectItemNoBroadcast(rItem
);
2103 // The concept of the text object:
2104 // ~~~~~~~~~~~~~~~~~~~~~~~~
2105 // Attributes/Variations:
2106 // - bool text frame / graphics object with caption
2107 // - bool FontWork (if it is not a text frame and not a ContourTextFrame)
2108 // - bool ContourTextFrame (if it is not a text frame and not Fontwork)
2109 // - long rotation angle (if it is not FontWork)
2110 // - long text frame margins (if it is not FontWork)
2111 // - bool FitToSize (if it is not FontWork)
2112 // - bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
2113 // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
2114 // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
2115 // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
2116 // - enum ticker text (if it is not FontWork)
2118 // Every derived object is either a text frame (bTextFrame=true)
2119 // or a drawing object with a caption (bTextFrame=false).
2121 // Default anchoring for text frames:
2122 // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
2123 // = static Pool defaults
2124 // Default anchoring for drawing objects with a caption:
2125 // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
2126 // via "hard" attribution of SdrAttrObj
2128 // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
2129 // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
2130 // left of the rectangle (aGeo.nRotationAngle)) which is the basis for anchoring
2131 // text. We then subtract the text frame margins from this rectangle, as a re-
2132 // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
2133 // calculate the anchoring point and the painting area, depending on the hori-
2134 // zontal and vertical adjustment of the text (SdrTextVertAdjust,
2135 // SdrTextHorzAdjust).
2136 // In the case of drawing objects with a caption the painting area might well
2137 // be larger than the anchoring area, for text frames on the other hand, it is
2138 // always of the same or a smaller size (except when there are negative text
2141 // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2142 // FitToSize is turned on, the painting area is always equal to the anchoring
2143 // area. Additionally, FitToSize doesn't allow automatic line breaks.
2145 // ContourTextFrame:
2146 // - long rotation angle
2147 // - long text frame margins (maybe later)
2148 // - bool FitToSize (maybe later)
2149 // - bool AutoGrowingWidth/Height (maybe much later)
2150 // - long Min/MaxFrameWidth/Height (maybe much later)
2151 // - enum horizontal text anchoring (maybe later, for now: left, centered)
2152 // - enum vertical text anchoring (maybe later, for now: top)
2153 // - enum ticker text (maybe later, maybe even with correct clipping)
2155 // When making changes, check these:
2160 // - Printing, Saving, Painting in neighboring View while editing
2161 // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2162 // - FillColorChanged while editing
2163 // - and many more...
2166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */