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 164327 : bool SdrTextObj::AdjustTextFrameWidthAndHeight( Rectangle& rR, bool bHgt, bool bWdt ) const
61 : {
62 164327 : if (!bTextFrame)
63 : // Not a text frame. Bail out.
64 0 : return false;
65 :
66 164327 : if (!pModel)
67 : // Model doesn't exist. Bail out.
68 0 : return false;
69 :
70 164327 : if (rR.IsEmpty())
71 : // Empty rectangle.
72 17135 : return false;
73 :
74 147192 : bool bFitToSize = IsFitToSize();
75 147192 : if (bFitToSize)
76 0 : return false;
77 :
78 147192 : bool bWdtGrow = bWdt && IsAutoGrowWidth();
79 147192 : bool bHgtGrow = bHgt && IsAutoGrowHeight();
80 147192 : if (!bWdtGrow && !bHgtGrow)
81 : // Not supposed to auto-adjust width or height.
82 62414 : return false;
83 :
84 84778 : SdrTextAniKind eAniKind = GetTextAniKind();
85 84778 : SdrTextAniDirection eAniDir = GetTextAniDirection();
86 :
87 84778 : bool bScroll = eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE;
88 84778 : bool bHScroll = bScroll && (eAniDir == SDRTEXTANI_LEFT || eAniDir == SDRTEXTANI_RIGHT);
89 84778 : bool bVScroll = bScroll && (eAniDir == SDRTEXTANI_UP || eAniDir == SDRTEXTANI_DOWN);
90 :
91 84778 : Rectangle aOldRect = rR;
92 84778 : long nHgt = 0, nMinHgt = 0, nMaxHgt = 0;
93 84778 : long nWdt = 0, nMinWdt = 0, nMaxWdt = 0;
94 :
95 84778 : Size aNewSize = rR.GetSize();
96 84778 : aNewSize.Width()--; aNewSize.Height()--;
97 :
98 84778 : Size aMaxSiz(100000, 100000);
99 84778 : Size aTmpSiz = pModel->GetMaxObjSize();
100 :
101 84778 : if (aTmpSiz.Width())
102 4124 : aMaxSiz.Width() = aTmpSiz.Width();
103 84778 : if (aTmpSiz.Height())
104 4124 : aMaxSiz.Height() = aTmpSiz.Height();
105 :
106 84778 : if (bWdtGrow)
107 : {
108 35373 : nMinWdt = GetMinTextFrameWidth();
109 35373 : nMaxWdt = GetMaxTextFrameWidth();
110 35373 : if (nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width())
111 33662 : nMaxWdt = aMaxSiz.Width();
112 35373 : if (nMinWdt <= 0)
113 16728 : nMinWdt = 1;
114 :
115 35373 : aNewSize.Width() = nMaxWdt;
116 : }
117 :
118 84778 : if (bHgtGrow)
119 : {
120 84174 : nMinHgt = GetMinTextFrameHeight();
121 84174 : nMaxHgt = GetMaxTextFrameHeight();
122 84174 : if (nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height())
123 84174 : nMaxHgt = aMaxSiz.Height();
124 84174 : if (nMinHgt <= 0)
125 1831 : nMinHgt = 1;
126 :
127 84174 : aNewSize.Height() = nMaxHgt;
128 : }
129 :
130 84778 : long nHDist = GetTextLeftDistance() + GetTextRightDistance();
131 84778 : long nVDist = GetTextUpperDistance() + GetTextLowerDistance();
132 84778 : aNewSize.Width() -= nHDist;
133 84778 : aNewSize.Height() -= nVDist;
134 :
135 84778 : if (aNewSize.Width() < 2)
136 774 : aNewSize.Width() = 2;
137 84778 : if (aNewSize.Height() < 2)
138 0 : aNewSize.Height() = 2;
139 :
140 84778 : if (!IsInEditMode())
141 : {
142 84778 : if (bHScroll)
143 0 : aNewSize.Width() = 0x0FFFFFFF; // don't break ticker text
144 84778 : if (bVScroll)
145 0 : aNewSize.Height() = 0x0FFFFFFF;
146 : }
147 :
148 84778 : if (pEdtOutl)
149 : {
150 0 : pEdtOutl->SetMaxAutoPaperSize(aNewSize);
151 0 : 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 0 : nHgt = pEdtOutl->GetTextHeight() + 1; // a little tolerance
161 : }
162 : }
163 : else
164 : {
165 84778 : Outliner& rOutliner = ImpGetDrawOutliner();
166 84778 : rOutliner.SetPaperSize(aNewSize);
167 84778 : rOutliner.SetUpdateMode(true);
168 : // TODO: add the optimization with bPortionInfoChecked etc. here
169 84778 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
170 84778 : if (pOutlinerParaObject)
171 : {
172 78204 : rOutliner.SetText(*pOutlinerParaObject);
173 78204 : rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
174 : }
175 :
176 84778 : if (bWdtGrow)
177 : {
178 35373 : Size aSiz2(rOutliner.CalcTextSize());
179 35373 : nWdt = aSiz2.Width() + 1; // a little tolerance
180 35373 : if (bHgtGrow)
181 34769 : nHgt = aSiz2.Height() + 1; // a little tolerance
182 : }
183 : else
184 : {
185 49405 : nHgt = rOutliner.GetTextHeight() + 1; // a little tolerance
186 : }
187 84778 : rOutliner.Clear();
188 : }
189 :
190 84778 : if (nWdt < nMinWdt)
191 156 : nWdt = nMinWdt;
192 84778 : if (nWdt > nMaxWdt)
193 0 : nWdt = nMaxWdt;
194 84778 : nWdt += nHDist;
195 84778 : if (nWdt < 1)
196 38711 : nWdt = 1; // nHDist may be negative
197 84778 : if (nHgt < nMinHgt)
198 30604 : nHgt = nMinHgt;
199 84778 : if (nHgt > nMaxHgt)
200 20 : nHgt = nMaxHgt;
201 84778 : nHgt += nVDist;
202 84778 : if (nHgt < 1)
203 20 : nHgt = 1; // nVDist may be negative
204 84778 : long nWdtGrow = nWdt - (rR.Right() - rR.Left());
205 84778 : long nHgtGrow = nHgt - (rR.Bottom() - rR.Top());
206 :
207 84778 : if (nWdtGrow == 0)
208 1308 : bWdtGrow = false;
209 84778 : if (nHgtGrow == 0)
210 27231 : bHgtGrow = false;
211 :
212 84778 : if (!bWdtGrow && !bHgtGrow)
213 26858 : return false;
214 :
215 57920 : if (bWdtGrow)
216 : {
217 34077 : SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust();
218 :
219 34077 : if (eHAdj == SDRTEXTHORZADJUST_LEFT)
220 1703 : rR.Right() += nWdtGrow;
221 32374 : else if (eHAdj == SDRTEXTHORZADJUST_RIGHT)
222 13805 : rR.Left() -= nWdtGrow;
223 : else
224 : {
225 18569 : long nWdtGrow2 = nWdtGrow / 2;
226 18569 : rR.Left() -= nWdtGrow2;
227 18569 : rR.Right() = rR.Left() + nWdt;
228 : }
229 : }
230 :
231 57920 : if (bHgtGrow)
232 : {
233 56943 : SdrTextVertAdjust eVAdj = GetTextVerticalAdjust();
234 :
235 56943 : if (eVAdj == SDRTEXTVERTADJUST_TOP)
236 35637 : rR.Bottom() += nHgtGrow;
237 21306 : else if (eVAdj == SDRTEXTVERTADJUST_BOTTOM)
238 4248 : rR.Top() -= nHgtGrow;
239 : else
240 : {
241 17058 : long nHgtGrow2 = nHgtGrow / 2;
242 17058 : rR.Top() -= nHgtGrow2;
243 17058 : rR.Bottom() = rR.Top() + nHgt;
244 : }
245 : }
246 :
247 57920 : 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 57920 : return true;
259 : }
260 :
261 164385 : bool SdrTextObj::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
262 : {
263 164385 : bool bRet=AdjustTextFrameWidthAndHeight(aRect,bHgt,bWdt);
264 164385 : if (bRet) {
265 58004 : SetRectsDirty();
266 58004 : if (HAS_BASE(SdrRectObj,this)) { // this is a hack
267 57920 : static_cast<SdrRectObj*>(this)->SetXPolyDirty();
268 : }
269 58004 : if (HAS_BASE(SdrCaptionObj,this)) { // this is a hack
270 208 : static_cast<SdrCaptionObj*>(this)->ImpRecalcTail();
271 : }
272 : }
273 164385 : return bRet;
274 : }
275 :
276 44 : bool SdrTextObj::AdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt)
277 : {
278 44 : Rectangle aNeuRect(aRect);
279 44 : bool bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt);
280 44 : if (bRet) {
281 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
282 0 : aRect=aNeuRect;
283 0 : SetRectsDirty();
284 0 : if (HAS_BASE(SdrRectObj,this)) { // this is a hack
285 0 : static_cast<SdrRectObj*>(this)->SetXPolyDirty();
286 : }
287 0 : if (HAS_BASE(SdrCaptionObj,this)) { // this is a hack
288 0 : static_cast<SdrCaptionObj*>(this)->ImpRecalcTail();
289 : }
290 0 : SetChanged();
291 0 : BroadcastObjectChange();
292 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
293 : }
294 44 : return bRet;
295 : }
296 :
297 83984 : void SdrTextObj::ImpSetTextStyleSheetListeners()
298 : {
299 83984 : SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL;
300 83984 : if (pStylePool!=NULL)
301 : {
302 23560 : std::vector<OUString> aStyleNames;
303 23560 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
304 23560 : if (pOutlinerParaObject!=NULL)
305 : {
306 : // First, we collect all stylesheets contained in the ParaObject in
307 : // the container aStyles. The Family is always appended to the name
308 : // of the stylesheet.
309 22998 : const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject();
310 22998 : OUString aStyleName;
311 : SfxStyleFamily eStyleFam;
312 22998 : sal_Int32 nParaAnz=rTextObj.GetParagraphCount();
313 :
314 :
315 55710 : for(sal_Int32 nParaNum(0); nParaNum < nParaAnz; nParaNum++)
316 : {
317 32712 : rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam);
318 :
319 32712 : if (!aStyleName.isEmpty())
320 : {
321 32664 : AppendFamilyToStyleName(aStyleName, eStyleFam);
322 :
323 32664 : bool bFnd(false);
324 32664 : sal_uInt32 nNum(aStyleNames.size());
325 :
326 81974 : while(!bFnd && nNum > 0)
327 : {
328 : // we don't want duplicate stylesheets
329 16646 : nNum--;
330 16646 : bFnd = aStyleName == aStyleNames[nNum];
331 : }
332 :
333 32664 : if(!bFnd)
334 : {
335 25660 : aStyleNames.push_back(aStyleName);
336 : }
337 : }
338 22998 : }
339 : }
340 :
341 : // now convert the strings in the vector from names to StyleSheet*
342 47120 : std::set<SfxStyleSheet*> aStyleSheets;
343 72780 : while (!aStyleNames.empty()) {
344 25660 : OUString aName = aStyleNames.back();
345 25660 : aStyleNames.pop_back();
346 :
347 25660 : SfxStyleFamily eFam = ReadFamilyFromStyleName(aName);
348 25660 : SfxStyleSheetBase* pStyleBase = pStylePool->Find(aName,eFam);
349 25660 : SfxStyleSheet* pStyle = PTR_CAST(SfxStyleSheet,pStyleBase);
350 25660 : if (pStyle!=NULL && pStyle!=GetStyleSheet()) {
351 0 : aStyleSheets.insert(pStyle);
352 : }
353 25660 : }
354 : // now remove all superfluous stylesheets
355 23560 : sal_uIntPtr nNum=GetBroadcasterCount();
356 48218 : while (nNum>0) {
357 1098 : nNum--;
358 1098 : SfxBroadcaster* pBroadcast=GetBroadcasterJOE((sal_uInt16)nNum);
359 1098 : SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast);
360 1098 : if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // special case for stylesheet of the object
361 864 : if (aStyleSheets.find(pStyle)==aStyleSheets.end()) {
362 864 : EndListening(*pStyle);
363 : }
364 : }
365 : }
366 : // and finally, merge all stylesheets that are contained in aStyles with previous broadcasters
367 23560 : for(std::set<SfxStyleSheet*>::const_iterator it = aStyleSheets.begin(); it != aStyleSheets.end(); ++it) {
368 0 : SfxStyleSheet* pStyle=*it;
369 : // let StartListening see for itself if there's already a listener registered
370 0 : StartListening(*pStyle,true);
371 23560 : }
372 : }
373 83984 : }
374 :
375 : /** iterates over the paragraphs of a given SdrObject and removes all
376 : hard set character attributes with the which ids contained in the
377 : given vector
378 : */
379 0 : void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds )
380 : {
381 0 : sal_Int32 nText = getTextCount();
382 :
383 0 : while( --nText >= 0 )
384 : {
385 0 : SdrText* pText = getText( nText );
386 0 : OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
387 :
388 0 : if(pOutlinerParaObject)
389 : {
390 0 : Outliner* pOutliner = 0;
391 :
392 0 : if( pEdtOutl || (pText == getActiveText()) )
393 0 : pOutliner = pEdtOutl;
394 :
395 0 : if(!pOutliner)
396 : {
397 0 : pOutliner = &ImpGetDrawOutliner();
398 0 : pOutliner->SetText(*pOutlinerParaObject);
399 : }
400 :
401 0 : ESelection aSelAll( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL );
402 0 : std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() );
403 0 : while( aIter != rCharWhichIds.end() )
404 : {
405 0 : pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) );
406 : }
407 :
408 0 : if(!pEdtOutl || (pText != getActiveText()) )
409 : {
410 0 : const sal_Int32 nParaCount = pOutliner->GetParagraphCount();
411 0 : OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, nParaCount);
412 0 : pOutliner->Clear();
413 0 : NbcSetOutlinerParaObjectForText(pTemp, pText);
414 : }
415 : }
416 : }
417 0 : }
418 :
419 142151 : bool SdrTextObj::HasText() const
420 : {
421 142151 : if( pEdtOutl )
422 0 : return HasEditText();
423 :
424 142151 : OutlinerParaObject* pOPO = GetOutlinerParaObject();
425 :
426 142151 : bool bHasText = false;
427 142151 : if( pOPO )
428 : {
429 123312 : const EditTextObject& rETO = pOPO->GetTextObject();
430 123312 : sal_Int32 nParaCount = rETO.GetParagraphCount();
431 :
432 123312 : if( nParaCount > 0 )
433 123312 : bHasText = (nParaCount > 1) || (!rETO.GetText( 0 ).isEmpty());
434 : }
435 :
436 142151 : return bHasText;
437 : }
438 :
439 32672 : void SdrTextObj::AppendFamilyToStyleName(OUString& styleName, SfxStyleFamily family)
440 : {
441 32672 : OUStringBuffer aFam;
442 32672 : aFam.append(static_cast<sal_Int32>(family));
443 32672 : comphelper::string::padToLength(aFam, PADDING_LENGTH_FOR_STYLE_FAMILY , PADDING_CHARACTER_FOR_STYLE_FAMILY);
444 :
445 32672 : styleName += OUString('|');
446 32672 : styleName += aFam.makeStringAndClear();
447 32672 : }
448 :
449 25668 : SfxStyleFamily SdrTextObj::ReadFamilyFromStyleName(const OUString& styleName)
450 : {
451 25668 : OUString familyString = styleName.copy(styleName.getLength() - PADDING_LENGTH_FOR_STYLE_FAMILY);
452 25668 : familyString = comphelper::string::stripEnd(familyString, PADDING_CHARACTER_FOR_STYLE_FAMILY);
453 25668 : sal_uInt16 nFam = static_cast<sal_uInt16>(familyString.toInt32());
454 : assert(nFam != 0);
455 25668 : return static_cast<SfxStyleFamily>(nFam);
456 651 : }
457 :
458 :
459 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|