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 <comphelper/string.hxx>
21 #include <svl/style.hxx>
22 #include <svx/svdotext.hxx>
23 #include <svx/svdmodel.hxx>
24 #include <svx/svdoutl.hxx>
25 #include <svx/svdorect.hxx>
26 #include <svx/svdocapt.hxx>
27 #include <svx/svdetc.hxx>
28 #include <editeng/writingmodeitem.hxx>
29 #include <editeng/editdata.hxx>
30 #include <editeng/editeng.hxx>
31 #include <editeng/eeitem.hxx>
32 #include <editeng/flditem.hxx>
33 #include <svx/sdtfchim.hxx>
36 #include <editeng/editview.hxx>
37 #include <svl/smplhint.hxx>
38 #include <svl/whiter.hxx>
39 #include <editeng/outlobj.hxx>
40 #include <editeng/outliner.hxx>
41 #include <editeng/editobj.hxx>
42 #include <editeng/fhgtitem.hxx>
44 #include <editeng/charscaleitem.hxx>
45 #include <svl/itemiter.hxx>
46 #include <editeng/lrspitem.hxx>
47 #include <svl/itempool.hxx>
48 #include <editeng/numitem.hxx>
49 #include <editeng/postitem.hxx>
54 // The style family which is appended to the style names is padded to this many characters.
55 const short PADDING_LENGTH_FOR_STYLE_FAMILY
= 5;
56 // this character will be used to pad the style families when they are appended to the style names
57 const sal_Char PADDING_CHARACTER_FOR_STYLE_FAMILY
= ' ';
60 bool SdrTextObj::AdjustTextFrameWidthAndHeight( Rectangle
& rR
, bool bHgt
, bool bWdt
) const
63 // Not a text frame. Bail out.
67 // Model doesn't exist. Bail out.
74 bool bFitToSize
= IsFitToSize();
78 bool bWdtGrow
= bWdt
&& IsAutoGrowWidth();
79 bool bHgtGrow
= bHgt
&& IsAutoGrowHeight();
80 if (!bWdtGrow
&& !bHgtGrow
)
81 // Not supposed to auto-adjust width or height.
84 SdrTextAniKind eAniKind
= GetTextAniKind();
85 SdrTextAniDirection eAniDir
= GetTextAniDirection();
87 bool bScroll
= eAniKind
== SDRTEXTANI_SCROLL
|| eAniKind
== SDRTEXTANI_ALTERNATE
|| eAniKind
== SDRTEXTANI_SLIDE
;
88 bool bHScroll
= bScroll
&& (eAniDir
== SDRTEXTANI_LEFT
|| eAniDir
== SDRTEXTANI_RIGHT
);
89 bool bVScroll
= bScroll
&& (eAniDir
== SDRTEXTANI_UP
|| eAniDir
== SDRTEXTANI_DOWN
);
91 Rectangle aOldRect
= rR
;
92 long nHgt
= 0, nMinHgt
= 0, nMaxHgt
= 0;
93 long nWdt
= 0, nMinWdt
= 0, nMaxWdt
= 0;
95 Size aNewSize
= rR
.GetSize();
96 aNewSize
.Width()--; aNewSize
.Height()--;
98 Size
aMaxSiz(100000, 100000);
99 Size aTmpSiz
= pModel
->GetMaxObjSize();
102 aMaxSiz
.Width() = aTmpSiz
.Width();
103 if (aTmpSiz
.Height())
104 aMaxSiz
.Height() = aTmpSiz
.Height();
108 nMinWdt
= GetMinTextFrameWidth();
109 nMaxWdt
= GetMaxTextFrameWidth();
110 if (nMaxWdt
== 0 || nMaxWdt
> aMaxSiz
.Width())
111 nMaxWdt
= aMaxSiz
.Width();
115 aNewSize
.Width() = nMaxWdt
;
120 nMinHgt
= GetMinTextFrameHeight();
121 nMaxHgt
= GetMaxTextFrameHeight();
122 if (nMaxHgt
== 0 || nMaxHgt
> aMaxSiz
.Height())
123 nMaxHgt
= aMaxSiz
.Height();
127 aNewSize
.Height() = nMaxHgt
;
130 long nHDist
= GetTextLeftDistance() + GetTextRightDistance();
131 long nVDist
= GetTextUpperDistance() + GetTextLowerDistance();
132 aNewSize
.Width() -= nHDist
;
133 aNewSize
.Height() -= nVDist
;
135 if (aNewSize
.Width() < 2)
136 aNewSize
.Width() = 2;
137 if (aNewSize
.Height() < 2)
138 aNewSize
.Height() = 2;
143 aNewSize
.Width() = 0x0FFFFFFF; // don't break ticker text
145 aNewSize
.Height() = 0x0FFFFFFF;
150 pEdtOutl
->SetMaxAutoPaperSize(aNewSize
);
153 Size
aSiz2(pEdtOutl
->CalcTextSize());
154 nWdt
= aSiz2
.Width() + 1; // a little tolerance
156 nHgt
= aSiz2
.Height() + 1; // a little tolerance
160 nHgt
= pEdtOutl
->GetTextHeight() + 1; // a little tolerance
165 Outliner
& rOutliner
= ImpGetDrawOutliner();
166 rOutliner
.SetPaperSize(aNewSize
);
167 rOutliner
.SetUpdateMode(true);
168 // TODO: add the optimization with bPortionInfoChecked etc. here
169 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
170 if (pOutlinerParaObject
)
172 rOutliner
.SetText(*pOutlinerParaObject
);
173 rOutliner
.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem
&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT
)).GetValue());
178 Size
aSiz2(rOutliner
.CalcTextSize());
179 nWdt
= aSiz2
.Width() + 1; // a little tolerance
181 nHgt
= aSiz2
.Height() + 1; // a little tolerance
185 nHgt
= rOutliner
.GetTextHeight() + 1; // a little tolerance
196 nWdt
= 1; // nHDist may be negative
203 nHgt
= 1; // nVDist may be negative
204 long nWdtGrow
= nWdt
- (rR
.Right() - rR
.Left());
205 long nHgtGrow
= nHgt
- (rR
.Bottom() - rR
.Top());
212 if (!bWdtGrow
&& !bHgtGrow
)
217 SdrTextHorzAdjust eHAdj
= GetTextHorizontalAdjust();
219 if (eHAdj
== SDRTEXTHORZADJUST_LEFT
)
220 rR
.Right() += nWdtGrow
;
221 else if (eHAdj
== SDRTEXTHORZADJUST_RIGHT
)
222 rR
.Left() -= nWdtGrow
;
225 long nWdtGrow2
= nWdtGrow
/ 2;
226 rR
.Left() -= nWdtGrow2
;
227 rR
.Right() = rR
.Left() + nWdt
;
233 SdrTextVertAdjust eVAdj
= GetTextVerticalAdjust();
235 if (eVAdj
== SDRTEXTVERTADJUST_TOP
)
236 rR
.Bottom() += nHgtGrow
;
237 else if (eVAdj
== SDRTEXTVERTADJUST_BOTTOM
)
238 rR
.Top() -= nHgtGrow
;
241 long nHgtGrow2
= nHgtGrow
/ 2;
242 rR
.Top() -= nHgtGrow2
;
243 rR
.Bottom() = rR
.Top() + nHgt
;
247 if (aGeo
.nRotationAngle
)
249 // Object is rotated.
250 Point
aD1(rR
.TopLeft());
251 aD1
-= aOldRect
.TopLeft();
253 RotatePoint(aD2
, Point(), aGeo
.nSin
, aGeo
.nCos
);
255 rR
.Move(aD2
.X(), aD2
.Y());
261 bool SdrTextObj::NbcAdjustTextFrameWidthAndHeight(bool bHgt
, bool bWdt
)
263 bool bRet
= AdjustTextFrameWidthAndHeight(maRect
,bHgt
,bWdt
);
267 if (HAS_BASE(SdrRectObj
,this)) { // this is a hack
268 static_cast<SdrRectObj
*>(this)->SetXPolyDirty();
270 if (HAS_BASE(SdrCaptionObj
,this)) { // this is a hack
271 static_cast<SdrCaptionObj
*>(this)->ImpRecalcTail();
277 bool SdrTextObj::AdjustTextFrameWidthAndHeight(bool bHgt
, bool bWdt
)
279 Rectangle
aNeuRect(maRect
);
280 bool bRet
=AdjustTextFrameWidthAndHeight(aNeuRect
,bHgt
,bWdt
);
282 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
285 if (HAS_BASE(SdrRectObj
,this)) { // this is a hack
286 static_cast<SdrRectObj
*>(this)->SetXPolyDirty();
288 if (HAS_BASE(SdrCaptionObj
,this)) { // this is a hack
289 static_cast<SdrCaptionObj
*>(this)->ImpRecalcTail();
292 BroadcastObjectChange();
293 SendUserCall(SDRUSERCALL_RESIZE
,aBoundRect0
);
298 void SdrTextObj::ImpSetTextStyleSheetListeners()
300 SfxStyleSheetBasePool
* pStylePool
=pModel
!=NULL
? pModel
->GetStyleSheetPool() : NULL
;
301 if (pStylePool
!=NULL
)
303 std::vector
<OUString
> aStyleNames
;
304 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
305 if (pOutlinerParaObject
!=NULL
)
307 // First, we collect all stylesheets contained in the ParaObject in
308 // the container aStyles. The Family is always appended to the name
309 // of the stylesheet.
310 const EditTextObject
& rTextObj
=pOutlinerParaObject
->GetTextObject();
312 SfxStyleFamily eStyleFam
;
313 sal_Int32 nParaAnz
=rTextObj
.GetParagraphCount();
316 for(sal_Int32
nParaNum(0); nParaNum
< nParaAnz
; nParaNum
++)
318 rTextObj
.GetStyleSheet(nParaNum
, aStyleName
, eStyleFam
);
320 if (!aStyleName
.isEmpty())
322 AppendFamilyToStyleName(aStyleName
, eStyleFam
);
325 sal_uInt32
nNum(aStyleNames
.size());
327 while(!bFnd
&& nNum
> 0)
329 // we don't want duplicate stylesheets
331 bFnd
= aStyleName
== aStyleNames
[nNum
];
336 aStyleNames
.push_back(aStyleName
);
342 // now convert the strings in the vector from names to StyleSheet*
343 std::set
<SfxStyleSheet
*> aStyleSheets
;
344 while (!aStyleNames
.empty()) {
345 OUString aName
= aStyleNames
.back();
346 aStyleNames
.pop_back();
348 SfxStyleFamily eFam
= ReadFamilyFromStyleName(aName
);
349 SfxStyleSheetBase
* pStyleBase
= pStylePool
->Find(aName
,eFam
);
350 SfxStyleSheet
* pStyle
= PTR_CAST(SfxStyleSheet
,pStyleBase
);
351 if (pStyle
!=NULL
&& pStyle
!=GetStyleSheet()) {
352 aStyleSheets
.insert(pStyle
);
355 // now remove all superfluous stylesheets
356 sal_uIntPtr nNum
=GetBroadcasterCount();
359 SfxBroadcaster
* pBroadcast
=GetBroadcasterJOE((sal_uInt16
)nNum
);
360 SfxStyleSheet
* pStyle
=PTR_CAST(SfxStyleSheet
,pBroadcast
);
361 if (pStyle
!=NULL
&& pStyle
!=GetStyleSheet()) { // special case for stylesheet of the object
362 if (aStyleSheets
.find(pStyle
)==aStyleSheets
.end()) {
363 EndListening(*pStyle
);
367 // and finally, merge all stylesheets that are contained in aStyles with previous broadcasters
368 for(std::set
<SfxStyleSheet
*>::const_iterator it
= aStyleSheets
.begin(); it
!= aStyleSheets
.end(); ++it
) {
369 SfxStyleSheet
* pStyle
=*it
;
370 // let StartListening see for itself if there's already a listener registered
371 StartListening(*pStyle
,true);
376 /** iterates over the paragraphs of a given SdrObject and removes all
377 hard set character attributes with the which ids contained in the
380 void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector
<sal_uInt16
>& rCharWhichIds
)
382 sal_Int32 nText
= getTextCount();
384 while( --nText
>= 0 )
386 SdrText
* pText
= getText( nText
);
387 OutlinerParaObject
* pOutlinerParaObject
= pText
? pText
->GetOutlinerParaObject() : 0;
389 if(pOutlinerParaObject
)
391 Outliner
* pOutliner
= 0;
393 if( pEdtOutl
|| (pText
== getActiveText()) )
394 pOutliner
= pEdtOutl
;
398 pOutliner
= &ImpGetDrawOutliner();
399 pOutliner
->SetText(*pOutlinerParaObject
);
402 ESelection
aSelAll( 0, 0, EE_PARA_ALL
, EE_TEXTPOS_ALL
);
403 std::vector
<sal_uInt16
>::const_iterator
aIter( rCharWhichIds
.begin() );
404 while( aIter
!= rCharWhichIds
.end() )
406 pOutliner
->RemoveAttribs( aSelAll
, false, (*aIter
++) );
409 if(!pEdtOutl
|| (pText
!= getActiveText()) )
411 const sal_Int32 nParaCount
= pOutliner
->GetParagraphCount();
412 OutlinerParaObject
* pTemp
= pOutliner
->CreateParaObject(0, nParaCount
);
414 NbcSetOutlinerParaObjectForText(pTemp
, pText
);
420 bool SdrTextObj::HasText() const
423 return HasEditText();
425 OutlinerParaObject
* pOPO
= GetOutlinerParaObject();
427 bool bHasText
= false;
430 const EditTextObject
& rETO
= pOPO
->GetTextObject();
431 sal_Int32 nParaCount
= rETO
.GetParagraphCount();
434 bHasText
= (nParaCount
> 1) || (!rETO
.GetText( 0 ).isEmpty());
440 void SdrTextObj::AppendFamilyToStyleName(OUString
& styleName
, SfxStyleFamily family
)
443 aFam
.append(static_cast<sal_Int32
>(family
));
444 comphelper::string::padToLength(aFam
, PADDING_LENGTH_FOR_STYLE_FAMILY
, PADDING_CHARACTER_FOR_STYLE_FAMILY
);
446 styleName
+= OUString('|');
447 styleName
+= aFam
.makeStringAndClear();
450 SfxStyleFamily
SdrTextObj::ReadFamilyFromStyleName(const OUString
& styleName
)
452 OUString familyString
= styleName
.copy(styleName
.getLength() - PADDING_LENGTH_FOR_STYLE_FAMILY
);
453 familyString
= comphelper::string::stripEnd(familyString
, PADDING_CHARACTER_FOR_STYLE_FAMILY
);
454 sal_uInt16 nFam
= static_cast<sal_uInt16
>(familyString
.toInt32());
456 return static_cast<SfxStyleFamily
>(nFam
);
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */