bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdotxat.cxx
blob52e7150ac9222d6924fff4d797e6589851ab46cc
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 <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>
51 #include <set>
53 namespace {
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
62 if (!bTextFrame)
63 // Not a text frame. Bail out.
64 return false;
66 if (!pModel)
67 // Model doesn't exist. Bail out.
68 return false;
70 if (rR.IsEmpty())
71 // Empty rectangle.
72 return false;
74 bool bFitToSize = IsFitToSize();
75 if (bFitToSize)
76 return false;
78 bool bWdtGrow = bWdt && IsAutoGrowWidth();
79 bool bHgtGrow = bHgt && IsAutoGrowHeight();
80 if (!bWdtGrow && !bHgtGrow)
81 // Not supposed to auto-adjust width or height.
82 return false;
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();
101 if (aTmpSiz.Width())
102 aMaxSiz.Width() = aTmpSiz.Width();
103 if (aTmpSiz.Height())
104 aMaxSiz.Height() = aTmpSiz.Height();
106 if (bWdtGrow)
108 nMinWdt = GetMinTextFrameWidth();
109 nMaxWdt = GetMaxTextFrameWidth();
110 if (nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width())
111 nMaxWdt = aMaxSiz.Width();
112 if (nMinWdt <= 0)
113 nMinWdt = 1;
115 aNewSize.Width() = nMaxWdt;
118 if (bHgtGrow)
120 nMinHgt = GetMinTextFrameHeight();
121 nMaxHgt = GetMaxTextFrameHeight();
122 if (nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height())
123 nMaxHgt = aMaxSiz.Height();
124 if (nMinHgt <= 0)
125 nMinHgt = 1;
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;
140 if (!IsInEditMode())
142 if (bHScroll)
143 aNewSize.Width() = 0x0FFFFFFF; // don't break ticker text
144 if (bVScroll)
145 aNewSize.Height() = 0x0FFFFFFF;
148 if (pEdtOutl)
150 pEdtOutl->SetMaxAutoPaperSize(aNewSize);
151 if (bWdtGrow)
153 Size aSiz2(pEdtOutl->CalcTextSize());
154 nWdt = aSiz2.Width() + 1; // a little tolerance
155 if (bHgtGrow)
156 nHgt = aSiz2.Height() + 1; // a little tolerance
158 else
160 nHgt = pEdtOutl->GetTextHeight() + 1; // a little tolerance
163 else
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());
176 if (bWdtGrow)
178 Size aSiz2(rOutliner.CalcTextSize());
179 nWdt = aSiz2.Width() + 1; // a little tolerance
180 if (bHgtGrow)
181 nHgt = aSiz2.Height() + 1; // a little tolerance
183 else
185 nHgt = rOutliner.GetTextHeight() + 1; // a little tolerance
187 rOutliner.Clear();
190 if (nWdt < nMinWdt)
191 nWdt = nMinWdt;
192 if (nWdt > nMaxWdt)
193 nWdt = nMaxWdt;
194 nWdt += nHDist;
195 if (nWdt < 1)
196 nWdt = 1; // nHDist may be negative
197 if (nHgt < nMinHgt)
198 nHgt = nMinHgt;
199 if (nHgt > nMaxHgt)
200 nHgt = nMaxHgt;
201 nHgt += nVDist;
202 if (nHgt < 1)
203 nHgt = 1; // nVDist may be negative
204 long nWdtGrow = nWdt - (rR.Right() - rR.Left());
205 long nHgtGrow = nHgt - (rR.Bottom() - rR.Top());
207 if (nWdtGrow == 0)
208 bWdtGrow = false;
209 if (nHgtGrow == 0)
210 bHgtGrow = false;
212 if (!bWdtGrow && !bHgtGrow)
213 return false;
215 if (bWdtGrow)
217 SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust();
219 if (eHAdj == SDRTEXTHORZADJUST_LEFT)
220 rR.Right() += nWdtGrow;
221 else if (eHAdj == SDRTEXTHORZADJUST_RIGHT)
222 rR.Left() -= nWdtGrow;
223 else
225 long nWdtGrow2 = nWdtGrow / 2;
226 rR.Left() -= nWdtGrow2;
227 rR.Right() = rR.Left() + nWdt;
231 if (bHgtGrow)
233 SdrTextVertAdjust eVAdj = GetTextVerticalAdjust();
235 if (eVAdj == SDRTEXTVERTADJUST_TOP)
236 rR.Bottom() += nHgtGrow;
237 else if (eVAdj == SDRTEXTVERTADJUST_BOTTOM)
238 rR.Top() -= nHgtGrow;
239 else
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();
252 Point aD2(aD1);
253 RotatePoint(aD2, Point(), aGeo.nSin, aGeo.nCos);
254 aD2 -= aD1;
255 rR.Move(aD2.X(), aD2.Y());
258 return true;
261 bool SdrTextObj::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
263 bool bRet = AdjustTextFrameWidthAndHeight(maRect,bHgt,bWdt);
264 if (bRet)
266 SetRectsDirty();
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();
274 return bRet;
277 bool SdrTextObj::AdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
279 Rectangle aNeuRect(maRect);
280 bool bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt);
281 if (bRet) {
282 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
283 maRect = aNeuRect;
284 SetRectsDirty();
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();
291 SetChanged();
292 BroadcastObjectChange();
293 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
295 return bRet;
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();
311 OUString aStyleName;
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);
324 bool bFnd(false);
325 sal_uInt32 nNum(aStyleNames.size());
327 while(!bFnd && nNum > 0)
329 // we don't want duplicate stylesheets
330 nNum--;
331 bFnd = aStyleName == aStyleNames[nNum];
334 if(!bFnd)
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();
357 while (nNum>0) {
358 nNum--;
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
378 given vector
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;
396 if(!pOutliner)
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);
413 pOutliner->Clear();
414 NbcSetOutlinerParaObjectForText(pTemp, pText);
420 bool SdrTextObj::HasText() const
422 if( pEdtOutl )
423 return HasEditText();
425 OutlinerParaObject* pOPO = GetOutlinerParaObject();
427 bool bHasText = false;
428 if( pOPO )
430 const EditTextObject& rETO = pOPO->GetTextObject();
431 sal_Int32 nParaCount = rETO.GetParagraphCount();
433 if( nParaCount > 0 )
434 bHasText = (nParaCount > 1) || (!rETO.GetText( 0 ).isEmpty());
437 return bHasText;
440 void SdrTextObj::AppendFamilyToStyleName(OUString& styleName, SfxStyleFamily family)
442 OUStringBuffer aFam;
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());
455 assert(nFam != 0);
456 return static_cast<SfxStyleFamily>(nFam);
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */