Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
34 :
35 :
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>
43 :
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>
50 :
51 : #include <set>
52 :
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 = ' ';
58 : }
59 :
60 199323 : bool SdrTextObj::AdjustTextFrameWidthAndHeight( Rectangle& rR, bool bHgt, bool bWdt ) const
61 : {
62 199323 : if (!bTextFrame)
63 : // Not a text frame. Bail out.
64 0 : return false;
65 :
66 199323 : if (!pModel)
67 : // Model doesn't exist. Bail out.
68 0 : return false;
69 :
70 199323 : if (rR.IsEmpty())
71 : // Empty rectangle.
72 1495 : return false;
73 :
74 197828 : bool bFitToSize = IsFitToSize();
75 197828 : if (bFitToSize)
76 0 : return false;
77 :
78 197828 : bool bWdtGrow = bWdt && IsAutoGrowWidth();
79 197828 : bool bHgtGrow = bHgt && IsAutoGrowHeight();
80 197828 : if (!bWdtGrow && !bHgtGrow)
81 : // Not supposed to auto-adjust width or height.
82 64741 : return false;
83 :
84 133087 : SdrTextAniKind eAniKind = GetTextAniKind();
85 133087 : SdrTextAniDirection eAniDir = GetTextAniDirection();
86 :
87 133087 : bool bScroll = eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE;
88 133087 : bool bHScroll = bScroll && (eAniDir == SDRTEXTANI_LEFT || eAniDir == SDRTEXTANI_RIGHT);
89 133087 : bool bVScroll = bScroll && (eAniDir == SDRTEXTANI_UP || eAniDir == SDRTEXTANI_DOWN);
90 :
91 133087 : Rectangle aOldRect = rR;
92 133087 : long nHgt = 0, nMinHgt = 0, nMaxHgt = 0;
93 133087 : long nWdt = 0, nMinWdt = 0, nMaxWdt = 0;
94 :
95 133087 : Size aNewSize = rR.GetSize();
96 133087 : aNewSize.Width()--; aNewSize.Height()--;
97 :
98 133087 : Size aMaxSiz(100000, 100000);
99 133087 : Size aTmpSiz = pModel->GetMaxObjSize();
100 :
101 133087 : if (aTmpSiz.Width())
102 2537 : aMaxSiz.Width() = aTmpSiz.Width();
103 133087 : if (aTmpSiz.Height())
104 2537 : aMaxSiz.Height() = aTmpSiz.Height();
105 :
106 133087 : if (bWdtGrow)
107 : {
108 57074 : nMinWdt = GetMinTextFrameWidth();
109 57074 : nMaxWdt = GetMaxTextFrameWidth();
110 57074 : if (nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width())
111 53589 : nMaxWdt = aMaxSiz.Width();
112 57074 : if (nMinWdt <= 0)
113 28578 : nMinWdt = 1;
114 :
115 57074 : aNewSize.Width() = nMaxWdt;
116 : }
117 :
118 133087 : if (bHgtGrow)
119 : {
120 132785 : nMinHgt = GetMinTextFrameHeight();
121 132785 : nMaxHgt = GetMaxTextFrameHeight();
122 132785 : if (nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height())
123 132785 : nMaxHgt = aMaxSiz.Height();
124 132785 : if (nMinHgt <= 0)
125 24919 : nMinHgt = 1;
126 :
127 132785 : aNewSize.Height() = nMaxHgt;
128 : }
129 :
130 133087 : long nHDist = GetTextLeftDistance() + GetTextRightDistance();
131 133087 : long nVDist = GetTextUpperDistance() + GetTextLowerDistance();
132 133087 : aNewSize.Width() -= nHDist;
133 133087 : aNewSize.Height() -= nVDist;
134 :
135 133087 : if (aNewSize.Width() < 2)
136 803 : aNewSize.Width() = 2;
137 133087 : if (aNewSize.Height() < 2)
138 0 : aNewSize.Height() = 2;
139 :
140 133087 : if (!IsInEditMode())
141 : {
142 133085 : if (bHScroll)
143 0 : aNewSize.Width() = 0x0FFFFFFF; // don't break ticker text
144 133085 : if (bVScroll)
145 0 : aNewSize.Height() = 0x0FFFFFFF;
146 : }
147 :
148 133087 : if (pEdtOutl)
149 : {
150 4 : pEdtOutl->SetMaxAutoPaperSize(aNewSize);
151 4 : if (bWdtGrow)
152 : {
153 0 : Size aSiz2(pEdtOutl->CalcTextSize());
154 0 : nWdt = aSiz2.Width() + 1; // a little tolerance
155 0 : if (bHgtGrow)
156 0 : nHgt = aSiz2.Height() + 1; // a little tolerance
157 : }
158 : else
159 : {
160 4 : nHgt = pEdtOutl->GetTextHeight() + 1; // a little tolerance
161 : }
162 : }
163 : else
164 : {
165 133083 : Outliner& rOutliner = ImpGetDrawOutliner();
166 133083 : rOutliner.SetPaperSize(aNewSize);
167 133083 : rOutliner.SetUpdateMode(true);
168 : // TODO: add the optimization with bPortionInfoChecked etc. here
169 133083 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
170 133083 : if (pOutlinerParaObject)
171 : {
172 105149 : rOutliner.SetText(*pOutlinerParaObject);
173 105149 : rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
174 : }
175 :
176 133083 : if (bWdtGrow)
177 : {
178 57074 : Size aSiz2(rOutliner.CalcTextSize());
179 57074 : nWdt = aSiz2.Width() + 1; // a little tolerance
180 57074 : if (bHgtGrow)
181 56772 : nHgt = aSiz2.Height() + 1; // a little tolerance
182 : }
183 : else
184 : {
185 76009 : nHgt = rOutliner.GetTextHeight() + 1; // a little tolerance
186 : }
187 133083 : rOutliner.Clear();
188 : }
189 :
190 133087 : if (nWdt < nMinWdt)
191 76 : nWdt = nMinWdt;
192 133087 : if (nWdt > nMaxWdt)
193 0 : nWdt = nMaxWdt;
194 133087 : nWdt += nHDist;
195 133087 : if (nWdt < 1)
196 66637 : nWdt = 1; // nHDist may be negative
197 133087 : if (nHgt < nMinHgt)
198 30434 : nHgt = nMinHgt;
199 133087 : if (nHgt > nMaxHgt)
200 10 : nHgt = nMaxHgt;
201 133087 : nHgt += nVDist;
202 133087 : if (nHgt < 1)
203 10 : nHgt = 1; // nVDist may be negative
204 133087 : long nWdtGrow = nWdt - (rR.Right() - rR.Left());
205 133087 : long nHgtGrow = nHgt - (rR.Bottom() - rR.Top());
206 :
207 133087 : if (nWdtGrow == 0)
208 2148 : bWdtGrow = false;
209 133087 : if (nHgtGrow == 0)
210 27723 : bHgtGrow = false;
211 :
212 133087 : if (!bWdtGrow && !bHgtGrow)
213 25654 : return false;
214 :
215 107433 : if (bWdtGrow)
216 : {
217 54932 : SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust();
218 :
219 54932 : if (eHAdj == SDRTEXTHORZADJUST_LEFT)
220 3979 : rR.Right() += nWdtGrow;
221 50953 : else if (eHAdj == SDRTEXTHORZADJUST_RIGHT)
222 22024 : rR.Left() -= nWdtGrow;
223 : else
224 : {
225 28929 : long nWdtGrow2 = nWdtGrow / 2;
226 28929 : rR.Left() -= nWdtGrow2;
227 28929 : rR.Right() = rR.Left() + nWdt;
228 : }
229 : }
230 :
231 107433 : if (bHgtGrow)
232 : {
233 105062 : SdrTextVertAdjust eVAdj = GetTextVerticalAdjust();
234 :
235 105062 : if (eVAdj == SDRTEXTVERTADJUST_TOP)
236 71457 : rR.Bottom() += nHgtGrow;
237 33605 : else if (eVAdj == SDRTEXTVERTADJUST_BOTTOM)
238 4014 : rR.Top() -= nHgtGrow;
239 : else
240 : {
241 29591 : long nHgtGrow2 = nHgtGrow / 2;
242 29591 : rR.Top() -= nHgtGrow2;
243 29591 : rR.Bottom() = rR.Top() + nHgt;
244 : }
245 : }
246 :
247 107433 : if (aGeo.nRotationAngle)
248 : {
249 : // Object is rotated.
250 4 : Point aD1(rR.TopLeft());
251 4 : aD1 -= aOldRect.TopLeft();
252 4 : Point aD2(aD1);
253 4 : RotatePoint(aD2, Point(), aGeo.nSin, aGeo.nCos);
254 4 : aD2 -= aD1;
255 4 : rR.Move(aD2.X(), aD2.Y());
256 : }
257 :
258 107433 : return true;
259 : }
260 :
261 199393 : bool SdrTextObj::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
262 : {
263 199393 : bool bRet = AdjustTextFrameWidthAndHeight(maRect,bHgt,bWdt);
264 199393 : if (bRet)
265 : {
266 107516 : SetRectsDirty();
267 107516 : if (HAS_BASE(SdrRectObj,this)) { // this is a hack
268 107433 : static_cast<SdrRectObj*>(this)->SetXPolyDirty();
269 : }
270 107516 : if (HAS_BASE(SdrCaptionObj,this)) { // this is a hack
271 111 : static_cast<SdrCaptionObj*>(this)->ImpRecalcTail();
272 : }
273 : }
274 199393 : return bRet;
275 : }
276 :
277 26 : bool SdrTextObj::AdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
278 : {
279 26 : Rectangle aNeuRect(maRect);
280 26 : bool bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt);
281 26 : if (bRet) {
282 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
283 0 : maRect = aNeuRect;
284 0 : SetRectsDirty();
285 0 : if (HAS_BASE(SdrRectObj,this)) { // this is a hack
286 0 : static_cast<SdrRectObj*>(this)->SetXPolyDirty();
287 : }
288 0 : if (HAS_BASE(SdrCaptionObj,this)) { // this is a hack
289 0 : static_cast<SdrCaptionObj*>(this)->ImpRecalcTail();
290 : }
291 0 : SetChanged();
292 0 : BroadcastObjectChange();
293 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
294 : }
295 26 : return bRet;
296 : }
297 :
298 105125 : void SdrTextObj::ImpSetTextStyleSheetListeners()
299 : {
300 105125 : SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL;
301 105125 : if (pStylePool!=NULL)
302 : {
303 20965 : std::vector<OUString> aStyleNames;
304 20965 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
305 20965 : if (pOutlinerParaObject!=NULL)
306 : {
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 20591 : const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject();
311 20591 : OUString aStyleName;
312 : SfxStyleFamily eStyleFam;
313 20591 : sal_Int32 nParaAnz=rTextObj.GetParagraphCount();
314 :
315 :
316 48113 : for(sal_Int32 nParaNum(0); nParaNum < nParaAnz; nParaNum++)
317 : {
318 27522 : rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam);
319 :
320 27522 : if (!aStyleName.isEmpty())
321 : {
322 27471 : AppendFamilyToStyleName(aStyleName, eStyleFam);
323 :
324 27471 : bool bFnd(false);
325 27471 : sal_uInt32 nNum(aStyleNames.size());
326 :
327 68199 : while(!bFnd && nNum > 0)
328 : {
329 : // we don't want duplicate stylesheets
330 13257 : nNum--;
331 13257 : bFnd = aStyleName == aStyleNames[nNum];
332 : }
333 :
334 27471 : if(!bFnd)
335 : {
336 22989 : aStyleNames.push_back(aStyleName);
337 : }
338 : }
339 20591 : }
340 : }
341 :
342 : // now convert the strings in the vector from names to StyleSheet*
343 41930 : std::set<SfxStyleSheet*> aStyleSheets;
344 64919 : while (!aStyleNames.empty()) {
345 22989 : OUString aName = aStyleNames.back();
346 22989 : aStyleNames.pop_back();
347 :
348 22989 : SfxStyleFamily eFam = ReadFamilyFromStyleName(aName);
349 22989 : SfxStyleSheetBase* pStyleBase = pStylePool->Find(aName,eFam);
350 22989 : SfxStyleSheet* pStyle = PTR_CAST(SfxStyleSheet,pStyleBase);
351 22989 : if (pStyle!=NULL && pStyle!=GetStyleSheet()) {
352 0 : aStyleSheets.insert(pStyle);
353 : }
354 22989 : }
355 : // now remove all superfluous stylesheets
356 20965 : sal_uIntPtr nNum=GetBroadcasterCount();
357 42792 : while (nNum>0) {
358 862 : nNum--;
359 862 : SfxBroadcaster* pBroadcast=GetBroadcasterJOE((sal_uInt16)nNum);
360 862 : SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast);
361 862 : if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // special case for stylesheet of the object
362 656 : if (aStyleSheets.find(pStyle)==aStyleSheets.end()) {
363 656 : EndListening(*pStyle);
364 : }
365 : }
366 : }
367 : // and finally, merge all stylesheets that are contained in aStyles with previous broadcasters
368 20965 : for(std::set<SfxStyleSheet*>::const_iterator it = aStyleSheets.begin(); it != aStyleSheets.end(); ++it) {
369 0 : SfxStyleSheet* pStyle=*it;
370 : // let StartListening see for itself if there's already a listener registered
371 0 : StartListening(*pStyle,true);
372 20965 : }
373 : }
374 105125 : }
375 :
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
379 : */
380 0 : void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds )
381 : {
382 0 : sal_Int32 nText = getTextCount();
383 :
384 0 : while( --nText >= 0 )
385 : {
386 0 : SdrText* pText = getText( nText );
387 0 : OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
388 :
389 0 : if(pOutlinerParaObject)
390 : {
391 0 : Outliner* pOutliner = 0;
392 :
393 0 : if( pEdtOutl || (pText == getActiveText()) )
394 0 : pOutliner = pEdtOutl;
395 :
396 0 : if(!pOutliner)
397 : {
398 0 : pOutliner = &ImpGetDrawOutliner();
399 0 : pOutliner->SetText(*pOutlinerParaObject);
400 : }
401 :
402 0 : ESelection aSelAll( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL );
403 0 : std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() );
404 0 : while( aIter != rCharWhichIds.end() )
405 : {
406 0 : pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) );
407 : }
408 :
409 0 : if(!pEdtOutl || (pText != getActiveText()) )
410 : {
411 0 : const sal_Int32 nParaCount = pOutliner->GetParagraphCount();
412 0 : OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, nParaCount);
413 0 : pOutliner->Clear();
414 0 : NbcSetOutlinerParaObjectForText(pTemp, pText);
415 : }
416 : }
417 : }
418 0 : }
419 :
420 128550 : bool SdrTextObj::HasText() const
421 : {
422 128550 : if( pEdtOutl )
423 7 : return HasEditText();
424 :
425 128543 : OutlinerParaObject* pOPO = GetOutlinerParaObject();
426 :
427 128543 : bool bHasText = false;
428 128543 : if( pOPO )
429 : {
430 117647 : const EditTextObject& rETO = pOPO->GetTextObject();
431 117647 : sal_Int32 nParaCount = rETO.GetParagraphCount();
432 :
433 117647 : if( nParaCount > 0 )
434 117647 : bHasText = (nParaCount > 1) || (!rETO.GetText( 0 ).isEmpty());
435 : }
436 :
437 128543 : return bHasText;
438 : }
439 :
440 27475 : void SdrTextObj::AppendFamilyToStyleName(OUString& styleName, SfxStyleFamily family)
441 : {
442 27475 : OUStringBuffer aFam;
443 27475 : aFam.append(static_cast<sal_Int32>(family));
444 27475 : comphelper::string::padToLength(aFam, PADDING_LENGTH_FOR_STYLE_FAMILY , PADDING_CHARACTER_FOR_STYLE_FAMILY);
445 :
446 27475 : styleName += OUString('|');
447 27475 : styleName += aFam.makeStringAndClear();
448 27475 : }
449 :
450 22993 : SfxStyleFamily SdrTextObj::ReadFamilyFromStyleName(const OUString& styleName)
451 : {
452 22993 : OUString familyString = styleName.copy(styleName.getLength() - PADDING_LENGTH_FOR_STYLE_FAMILY);
453 22993 : familyString = comphelper::string::stripEnd(familyString, PADDING_CHARACTER_FOR_STYLE_FAMILY);
454 22993 : sal_uInt16 nFam = static_cast<sal_uInt16>(familyString.toInt32());
455 : assert(nFam != 0);
456 22993 : return static_cast<SfxStyleFamily>(nFam);
457 435 : }
458 :
459 :
460 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|