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 :
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 "svdglob.hxx"
30 : #include "svx/svdstr.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 <svl/itempool.hxx>
42 : #include <editeng/adjustitem.hxx>
43 : #include <editeng/flditem.hxx>
44 : #include <svx/xftouit.hxx>
45 : #include <tools/helpers.hxx>
46 : #include <svx/xflgrit.hxx>
47 : #include <svx/svdpool.hxx>
48 : #include <svx/xflclit.hxx>
49 : #include <svl/style.hxx>
50 : #include <editeng/editeng.hxx>
51 : #include <svl/itemiter.hxx>
52 : #include <sdr/properties/textproperties.hxx>
53 : #include <vcl/metaact.hxx>
54 : #include <svx/sdr/contact/viewcontactoftextobj.hxx>
55 : #include <basegfx/tuple/b2dtuple.hxx>
56 : #include <basegfx/matrix/b2dhommatrix.hxx>
57 : #include <basegfx/polygon/b2dpolygon.hxx>
58 : #include <drawinglayer/geometry/viewinformation2d.hxx>
59 : #include <vcl/virdev.hxx>
60 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 : #include "svdconv.hxx"
62 :
63 : using namespace com::sun::star;
64 :
65 :
66 : // BaseProperties section
67 :
68 21617 : sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties()
69 : {
70 21617 : return new sdr::properties::TextProperties(*this);
71 : }
72 :
73 :
74 : // DrawContact section
75 :
76 0 : sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact()
77 : {
78 0 : return new sdr::contact::ViewContactOfTextObj(*this);
79 : }
80 :
81 :
82 :
83 6960909 : TYPEINIT1(SdrTextObj,SdrAttrObj);
84 :
85 38101 : SdrTextObj::SdrTextObj()
86 : : SdrAttrObj(),
87 : mpText(NULL),
88 : pEdtOutl(NULL),
89 : pFormTextBoundRect(NULL),
90 38101 : eTextKind(OBJ_TEXT)
91 : {
92 38101 : bTextSizeDirty=false;
93 38101 : bTextFrame=false;
94 38101 : bPortionInfoChecked=false;
95 38101 : bNoShear=false;
96 38101 : bNoRotate=false;
97 38101 : bNoMirror=false;
98 38101 : bDisableAutoWidthOnDragging=false;
99 :
100 38101 : mbInEditMode = false;
101 38101 : mbTextHidden = false;
102 38101 : mbTextAnimationAllowed = true;
103 38101 : maTextEditOffset = Point(0, 0);
104 :
105 : // #i25616#
106 38101 : mbSupportTextIndentingOnLineWidthChange = true;
107 38101 : mbInDownScale = false;
108 38101 : }
109 :
110 1796 : SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
111 : : SdrAttrObj(),
112 : maRect(rNewRect),
113 : mpText(NULL),
114 : pEdtOutl(NULL),
115 : pFormTextBoundRect(NULL),
116 1796 : eTextKind(OBJ_TEXT)
117 : {
118 1796 : bTextSizeDirty=false;
119 1796 : bTextFrame=false;
120 1796 : bPortionInfoChecked=false;
121 1796 : bNoShear=false;
122 1796 : bNoRotate=false;
123 1796 : bNoMirror=false;
124 1796 : bDisableAutoWidthOnDragging=false;
125 1796 : ImpJustifyRect(maRect);
126 :
127 1796 : mbInEditMode = false;
128 1796 : mbTextHidden = false;
129 1796 : mbTextAnimationAllowed = true;
130 1796 : mbInDownScale = false;
131 1796 : maTextEditOffset = Point(0, 0);
132 :
133 : // #i25616#
134 1796 : mbSupportTextIndentingOnLineWidthChange = true;
135 1796 : }
136 :
137 5996 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind)
138 : : SdrAttrObj(),
139 : mpText(NULL),
140 : pEdtOutl(NULL),
141 : pFormTextBoundRect(NULL),
142 5996 : eTextKind(eNewTextKind)
143 : {
144 5996 : bTextSizeDirty=false;
145 5996 : bTextFrame=true;
146 5996 : bPortionInfoChecked=false;
147 5996 : bNoShear=true;
148 5996 : bNoRotate=false;
149 5996 : bNoMirror=true;
150 5996 : bDisableAutoWidthOnDragging=false;
151 :
152 5996 : mbInEditMode = false;
153 5996 : mbTextHidden = false;
154 5996 : mbTextAnimationAllowed = true;
155 5996 : mbInDownScale = false;
156 5996 : maTextEditOffset = Point(0, 0);
157 :
158 : // #i25616#
159 5996 : mbSupportTextIndentingOnLineWidthChange = true;
160 5996 : }
161 :
162 22276 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect)
163 : : SdrAttrObj(),
164 : maRect(rNewRect),
165 : mpText(NULL),
166 : pEdtOutl(NULL),
167 : pFormTextBoundRect(NULL),
168 22276 : eTextKind(eNewTextKind)
169 : {
170 22276 : bTextSizeDirty=false;
171 22276 : bTextFrame=true;
172 22276 : bPortionInfoChecked=false;
173 22276 : bNoShear=true;
174 22276 : bNoRotate=false;
175 22276 : bNoMirror=true;
176 22276 : bDisableAutoWidthOnDragging=false;
177 22276 : ImpJustifyRect(maRect);
178 :
179 22276 : mbInEditMode = false;
180 22276 : mbTextHidden = false;
181 22276 : mbTextAnimationAllowed = true;
182 22276 : mbInDownScale = false;
183 22276 : maTextEditOffset = Point(0, 0);
184 :
185 : // #i25616#
186 22276 : mbSupportTextIndentingOnLineWidthChange = true;
187 22276 : }
188 :
189 134792 : SdrTextObj::~SdrTextObj()
190 : {
191 67396 : if( pModel )
192 : {
193 62933 : SdrOutliner& rOutl = pModel->GetHitTestOutliner();
194 62933 : if( rOutl.GetTextObj() == this )
195 0 : rOutl.SetTextObj( NULL );
196 : }
197 :
198 67396 : delete mpText;
199 :
200 67396 : delete pFormTextBoundRect;
201 :
202 67396 : ImpLinkAbmeldung();
203 67396 : }
204 :
205 0 : void SdrTextObj::FitFrameToTextSize()
206 : {
207 : DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!");
208 0 : ImpJustifyRect(maRect);
209 :
210 0 : SdrText* pText = getActiveText();
211 0 : if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL)
212 : {
213 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
214 0 : rOutliner.SetPaperSize(Size(maRect.Right()-maRect.Left(),maRect.Bottom()-maRect.Top()));
215 0 : rOutliner.SetUpdateMode(true);
216 0 : rOutliner.SetText(*pText->GetOutlinerParaObject());
217 0 : Size aNewSize(rOutliner.CalcTextSize());
218 0 : rOutliner.Clear();
219 0 : aNewSize.Width()++; // because of possible rounding errors
220 0 : aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance();
221 0 : aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
222 0 : Rectangle aNewRect(maRect);
223 0 : aNewRect.SetSize(aNewSize);
224 0 : ImpJustifyRect(aNewRect);
225 0 : if (aNewRect!=maRect) {
226 0 : SetLogicRect(aNewRect);
227 : }
228 : }
229 0 : }
230 :
231 371 : void SdrTextObj::NbcSetText(const OUString& rStr)
232 : {
233 371 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
234 371 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
235 371 : rOutliner.SetUpdateMode(true);
236 371 : rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 ));
237 371 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
238 371 : Size aSiz(rOutliner.CalcTextSize());
239 371 : rOutliner.Clear();
240 371 : NbcSetOutlinerParaObject(pNewText);
241 371 : aTextSize=aSiz;
242 371 : bTextSizeDirty=false;
243 371 : }
244 :
245 25 : void SdrTextObj::SetText(const OUString& rStr)
246 : {
247 25 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
248 25 : NbcSetText(rStr);
249 25 : SetChanged();
250 25 : BroadcastObjectChange();
251 25 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
252 25 : }
253 :
254 0 : void SdrTextObj::NbcSetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
255 : {
256 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
257 0 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
258 0 : rOutliner.Read(rInput,rBaseURL,eFormat);
259 0 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
260 0 : rOutliner.SetUpdateMode(true);
261 0 : Size aSiz(rOutliner.CalcTextSize());
262 0 : rOutliner.Clear();
263 0 : NbcSetOutlinerParaObject(pNewText);
264 0 : aTextSize=aSiz;
265 0 : bTextSizeDirty=false;
266 0 : }
267 :
268 0 : void SdrTextObj::SetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
269 : {
270 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
271 0 : NbcSetText(rInput,rBaseURL,eFormat);
272 0 : SetChanged();
273 0 : BroadcastObjectChange();
274 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
275 0 : }
276 :
277 24 : const Size& SdrTextObj::GetTextSize() const
278 : {
279 24 : if (bTextSizeDirty)
280 : {
281 7 : Size aSiz;
282 7 : SdrText* pText = getActiveText();
283 7 : if( pText && pText->GetOutlinerParaObject ())
284 : {
285 7 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
286 7 : rOutliner.SetText(*pText->GetOutlinerParaObject());
287 7 : rOutliner.SetUpdateMode(true);
288 7 : aSiz=rOutliner.CalcTextSize();
289 7 : rOutliner.Clear();
290 : }
291 : // casting to nonconst twice
292 7 : const_cast<SdrTextObj*>(this)->aTextSize=aSiz;
293 7 : const_cast<SdrTextObj*>(this)->bTextSizeDirty=false;
294 : }
295 24 : return aTextSize;
296 : }
297 :
298 366573 : bool SdrTextObj::IsAutoGrowHeight() const
299 : {
300 366573 : if(!bTextFrame)
301 0 : return false; // AutoGrow only together with TextFrames
302 :
303 366573 : const SfxItemSet& rSet = GetObjectItemSet();
304 366573 : bool bRet = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
305 :
306 366573 : if(bRet)
307 : {
308 283238 : SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
309 :
310 283238 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
311 : {
312 0 : SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
313 :
314 0 : if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN)
315 : {
316 0 : bRet = false;
317 : }
318 : }
319 : }
320 366573 : return bRet;
321 : }
322 :
323 532857 : bool SdrTextObj::IsAutoGrowWidth() const
324 : {
325 532857 : if(!bTextFrame)
326 86 : return false; // AutoGrow only together with TextFrames
327 :
328 532771 : const SfxItemSet& rSet = GetObjectItemSet();
329 532771 : bool bRet = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
330 :
331 532771 : bool bInEditMOde = IsInEditMode();
332 :
333 532771 : if(!bInEditMOde && bRet)
334 : {
335 191765 : SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
336 :
337 191765 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
338 : {
339 0 : SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
340 :
341 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
342 : {
343 0 : bRet = false;
344 : }
345 : }
346 : }
347 532771 : return bRet;
348 : }
349 :
350 55160 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const
351 : {
352 55160 : return GetTextHorizontalAdjust(GetObjectItemSet());
353 : }
354 :
355 84411 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const
356 : {
357 84411 : if(IsContourTextFrame())
358 0 : return SDRTEXTHORZADJUST_BLOCK;
359 :
360 84411 : SdrTextHorzAdjust eRet = static_cast<const SdrTextHorzAdjustItem&>(rSet.Get(SDRATTR_TEXT_HORZADJUST)).GetValue();
361 :
362 84411 : bool bInEditMode = IsInEditMode();
363 :
364 84411 : if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK)
365 : {
366 5934 : SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
367 :
368 5934 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
369 : {
370 0 : SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
371 :
372 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
373 : {
374 0 : eRet = SDRTEXTHORZADJUST_LEFT;
375 : }
376 : }
377 : }
378 :
379 84411 : return eRet;
380 : } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
381 :
382 106145 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const
383 : {
384 106145 : return GetTextVerticalAdjust(GetObjectItemSet());
385 : }
386 :
387 135396 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const
388 : {
389 135396 : if(IsContourTextFrame())
390 0 : return SDRTEXTVERTADJUST_TOP;
391 :
392 : // Take care for vertical text animation here
393 135396 : SdrTextVertAdjust eRet = static_cast<const SdrTextVertAdjustItem&>(rSet.Get(SDRATTR_TEXT_VERTADJUST)).GetValue();
394 135396 : bool bInEditMode = IsInEditMode();
395 :
396 : // Take care for vertical text animation here
397 135396 : if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK)
398 : {
399 1 : SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
400 :
401 1 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
402 : {
403 0 : SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
404 :
405 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
406 : {
407 0 : eRet = SDRTEXTVERTADJUST_TOP;
408 : }
409 : }
410 : }
411 :
412 135396 : return eRet;
413 : } // defaults: TOP for text frame, CENTER for captions of drawing objects
414 :
415 187310 : void SdrTextObj::ImpJustifyRect(Rectangle& rRect)
416 : {
417 187310 : if (!rRect.IsEmpty()) {
418 181936 : rRect.Justify();
419 181936 : if (rRect.Left()==rRect.Right()) rRect.Right()++;
420 181936 : if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++;
421 : }
422 187310 : }
423 :
424 94157 : void SdrTextObj::ImpCheckShear()
425 : {
426 94157 : if (bNoShear && aGeo.nShearAngle!=0) {
427 0 : aGeo.nShearAngle=0;
428 0 : aGeo.nTan=0;
429 : }
430 94157 : }
431 :
432 0 : void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
433 : {
434 0 : bool bNoTextFrame=!IsTextFrame();
435 0 : rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nRotationAngle%9000==0;
436 0 : rInfo.bResizePropAllowed=true;
437 0 : rInfo.bRotateFreeAllowed=true;
438 0 : rInfo.bRotate90Allowed =true;
439 0 : rInfo.bMirrorFreeAllowed=bNoTextFrame;
440 0 : rInfo.bMirror45Allowed =bNoTextFrame;
441 0 : rInfo.bMirror90Allowed =bNoTextFrame;
442 :
443 : // allow transparency
444 0 : rInfo.bTransparenceAllowed = true;
445 :
446 : // gradient depends on fillstyle
447 0 : drawing::FillStyle eFillStyle = static_cast<const XFillStyleItem&>(GetObjectItem(XATTR_FILLSTYLE)).GetValue();
448 0 : rInfo.bGradientAllowed = (eFillStyle == drawing::FillStyle_GRADIENT);
449 0 : rInfo.bShearAllowed =bNoTextFrame;
450 0 : rInfo.bEdgeRadiusAllowed=true;
451 0 : bool bCanConv=ImpCanConvTextToCurve();
452 0 : rInfo.bCanConvToPath =bCanConv;
453 0 : rInfo.bCanConvToPoly =bCanConv;
454 0 : rInfo.bCanConvToPathLineToArea=bCanConv;
455 0 : rInfo.bCanConvToPolyLineToArea=bCanConv;
456 0 : rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
457 0 : }
458 :
459 0 : sal_uInt16 SdrTextObj::GetObjIdentifier() const
460 : {
461 0 : return sal_uInt16(eTextKind);
462 : }
463 :
464 31899 : bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner )
465 : {
466 31899 : bool bRet=false;
467 31899 : if(pOutliner)
468 : {
469 60 : Paragraph* p1stPara=pOutliner->GetParagraph( 0 );
470 60 : sal_Int32 nParaCount=pOutliner->GetParagraphCount();
471 60 : if(p1stPara==NULL)
472 0 : nParaCount=0;
473 :
474 60 : if(nParaCount==1)
475 : {
476 : // if it is only one paragraph, check if that paragraph is empty
477 60 : if( pOutliner->GetText(p1stPara).isEmpty() )
478 0 : nParaCount = 0;
479 : }
480 :
481 60 : bRet= nParaCount!=0;
482 : }
483 31899 : return bRet;
484 : }
485 :
486 7 : bool SdrTextObj::HasEditText() const
487 : {
488 7 : return HasTextImpl( pEdtOutl );
489 : }
490 :
491 167463 : void SdrTextObj::SetPage(SdrPage* pNewPage)
492 : {
493 167463 : bool bRemove=pNewPage==NULL && pPage!=NULL;
494 167463 : bool bInsert=pNewPage!=NULL && pPage==NULL;
495 167463 : bool bLinked=IsLinkedText();
496 :
497 167463 : if (bLinked && bRemove) {
498 0 : ImpLinkAbmeldung();
499 : }
500 :
501 167463 : SdrAttrObj::SetPage(pNewPage);
502 :
503 167463 : if (bLinked && bInsert) {
504 0 : ImpLinkAnmeldung();
505 : }
506 167463 : }
507 :
508 119517 : void SdrTextObj::SetModel(SdrModel* pNewModel)
509 : {
510 119517 : SdrModel* pOldModel=pModel;
511 119517 : bool bLinked=IsLinkedText();
512 119517 : bool bChg=pNewModel!=pModel;
513 :
514 119517 : if (bLinked && bChg)
515 : {
516 0 : ImpLinkAbmeldung();
517 : }
518 :
519 119517 : SdrAttrObj::SetModel(pNewModel);
520 :
521 119517 : if( bChg )
522 : {
523 62971 : if( pNewModel != 0 && pOldModel != 0 )
524 21 : SetTextSizeDirty();
525 :
526 62971 : sal_Int32 nCount = getTextCount();
527 125942 : for( sal_Int32 nText = 0; nText < nCount; nText++ )
528 : {
529 62971 : SdrText* pText = getText( nText );
530 62971 : if( pText )
531 62971 : pText->SetModel( pNewModel );
532 : }
533 : }
534 :
535 119517 : if (bLinked && bChg)
536 : {
537 0 : ImpLinkAnmeldung();
538 : }
539 119517 : }
540 :
541 0 : bool SdrTextObj::NbcSetEckenradius(long nRad)
542 : {
543 0 : SetObjectItem(makeSdrEckenradiusItem(nRad));
544 0 : return true;
545 : }
546 :
547 : // #115391# This implementation is based on the object size (aRect) and the
548 : // states of IsAutoGrowWidth/Height to correctly set TextMinFrameWidth/Height
549 148561 : void SdrTextObj::AdaptTextMinSize()
550 : {
551 148561 : if (!bTextFrame)
552 : // Only do this for text frame.
553 164924 : return;
554 :
555 69144 : if (pModel && pModel->IsPasteResize())
556 : // Don't do this during paste resize.
557 0 : return;
558 :
559 69144 : const bool bW = IsAutoGrowWidth();
560 69144 : const bool bH = IsAutoGrowHeight();
561 :
562 69144 : if (!bW && !bH)
563 : // No auto grow requested. Bail out.
564 6090 : return;
565 :
566 : SfxItemSet aSet(
567 63054 : *GetObjectItemSet().GetPool(),
568 : SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
569 : SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH, // contains SDRATTR_TEXT_MAXFRAMEWIDTH
570 63054 : 0, 0);
571 :
572 63054 : if(bW)
573 : {
574 : // Set minimum width.
575 30649 : const long nDist = GetTextLeftDistance() + GetTextRightDistance();
576 30649 : const long nW = std::max<long>(0, maRect.GetWidth() - 1 - nDist); // text width without margins
577 :
578 30649 : aSet.Put(makeSdrTextMinFrameWidthItem(nW));
579 :
580 30649 : if(!IsVerticalWriting() && bDisableAutoWidthOnDragging)
581 : {
582 0 : bDisableAutoWidthOnDragging = true;
583 0 : aSet.Put(makeSdrTextAutoGrowWidthItem(false));
584 : }
585 : }
586 :
587 63054 : if(bH)
588 : {
589 : // Set Minimum height.
590 63030 : const long nDist = GetTextUpperDistance() + GetTextLowerDistance();
591 63030 : const long nH = std::max<long>(0, maRect.GetHeight() - 1 - nDist); // text height without margins
592 :
593 63030 : aSet.Put(makeSdrTextMinFrameHeightItem(nH));
594 :
595 63030 : if(IsVerticalWriting() && bDisableAutoWidthOnDragging)
596 : {
597 0 : bDisableAutoWidthOnDragging = false;
598 0 : aSet.Put(makeSdrTextAutoGrowHeightItem(false));
599 : }
600 : }
601 :
602 63054 : SetObjectItemSet(aSet);
603 : }
604 :
605 0 : void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, bool bLineWidth ) const
606 : {
607 0 : basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly());
608 0 : basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L;
609 : basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
610 0 : -rAnchorRect.Left(), -rAnchorRect.Top()));
611 :
612 0 : if(aGeo.nRotationAngle)
613 : {
614 : // Unrotate!
615 0 : aMatrix.rotate(-aGeo.nRotationAngle * nPi180);
616 : }
617 :
618 0 : aXorPolyPolygon.transform(aMatrix);
619 :
620 0 : if( bLineWidth )
621 : {
622 : // Take line width into account.
623 : // When doing the hit test, avoid this. (Performance!)
624 0 : pContourPolyPolygon = new basegfx::B2DPolyPolygon();
625 :
626 : // test if shadow needs to be avoided for TakeContour()
627 0 : const SfxItemSet& rSet = GetObjectItemSet();
628 0 : bool bShadowOn = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_SHADOW)).GetValue();
629 :
630 : // #i33696#
631 : // Remember TextObject currently set at the DrawOutliner, it WILL be
632 : // replaced during calculating the outline since it uses an own paint
633 : // and that one uses the DrawOutliner, too.
634 0 : const SdrTextObj* pLastTextObject = rOutliner.GetTextObj();
635 :
636 0 : if(bShadowOn)
637 : {
638 : // force shadow off
639 0 : SdrObject* pCopy = Clone();
640 0 : pCopy->SetMergedItem(makeSdrShadowItem(false));
641 0 : *pContourPolyPolygon = pCopy->TakeContour();
642 0 : SdrObject::Free( pCopy );
643 : }
644 : else
645 : {
646 0 : *pContourPolyPolygon = TakeContour();
647 : }
648 :
649 : // #i33696#
650 : // restore remembered text object
651 0 : if(pLastTextObject != rOutliner.GetTextObj())
652 : {
653 0 : rOutliner.SetTextObj(pLastTextObject);
654 : }
655 :
656 0 : pContourPolyPolygon->transform(aMatrix);
657 : }
658 :
659 0 : rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon);
660 0 : delete pContourPolyPolygon;
661 0 : }
662 :
663 0 : void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
664 : {
665 0 : rRect=maRect;
666 0 : }
667 :
668 27 : void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
669 : {
670 27 : long nLeftDist=GetTextLeftDistance();
671 27 : long nRightDist=GetTextRightDistance();
672 27 : long nUpperDist=GetTextUpperDistance();
673 27 : long nLowerDist=GetTextLowerDistance();
674 27 : Rectangle aAnkRect(maRect); // the rectangle in which we anchor
675 27 : bool bFrame=IsTextFrame();
676 27 : if (!bFrame) {
677 6 : TakeUnrotatedSnapRect(aAnkRect);
678 : }
679 27 : Point aRotateRef(aAnkRect.TopLeft());
680 27 : aAnkRect.Left()+=nLeftDist;
681 27 : aAnkRect.Top()+=nUpperDist;
682 27 : aAnkRect.Right()-=nRightDist;
683 27 : aAnkRect.Bottom()-=nLowerDist;
684 :
685 : // Since sizes may be bigger than the object bounds it is necessary to
686 : // justify the rect now.
687 27 : ImpJustifyRect(aAnkRect);
688 :
689 27 : if (bFrame) {
690 : // TODO: Optimize this.
691 21 : if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // minimum size h and v: 2 px
692 21 : if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1;
693 : }
694 27 : if (aGeo.nRotationAngle!=0) {
695 0 : Point aTmpPt(aAnkRect.TopLeft());
696 0 : RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos);
697 0 : aTmpPt-=aAnkRect.TopLeft();
698 0 : aAnkRect.Move(aTmpPt.X(),aTmpPt.Y());
699 : }
700 27 : rAnchorRect=aAnkRect;
701 27 : }
702 :
703 9 : void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
704 : Rectangle* pAnchorRect, bool bLineWidth ) const
705 : {
706 9 : Rectangle aAnkRect; // the rectangle in which we anchor
707 9 : TakeTextAnchorRect(aAnkRect);
708 9 : SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
709 9 : SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
710 9 : SdrTextAniKind eAniKind=GetTextAniKind();
711 9 : SdrTextAniDirection eAniDirection=GetTextAniDirection();
712 :
713 9 : bool bFitToSize(IsFitToSize());
714 9 : bool bContourFrame=IsContourTextFrame();
715 :
716 9 : bool bFrame=IsTextFrame();
717 9 : EEControlBits nStat0=rOutliner.GetControlWord();
718 9 : Size aNullSize;
719 9 : if (!bContourFrame)
720 : {
721 9 : rOutliner.SetControlWord(nStat0|EEControlBits::AUTOPAGESIZE);
722 9 : rOutliner.SetMinAutoPaperSize(aNullSize);
723 9 : rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
724 : }
725 :
726 9 : if (!bFitToSize && !bContourFrame)
727 : {
728 9 : long nAnkWdt=aAnkRect.GetWidth();
729 9 : long nAnkHgt=aAnkRect.GetHeight();
730 9 : if (bFrame)
731 : {
732 7 : long nWdt=nAnkWdt;
733 7 : long nHgt=nAnkHgt;
734 :
735 7 : bool bInEditMode = IsInEditMode();
736 :
737 7 : if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE))
738 : {
739 : // unlimited paper size for ticker text
740 0 : if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000;
741 0 : if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000;
742 : }
743 :
744 : // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
745 7 : if(IsVerticalWriting())
746 : {
747 0 : nWdt = 1000000;
748 : }
749 : else
750 : {
751 7 : nHgt = 1000000;
752 : }
753 :
754 7 : rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt));
755 : }
756 :
757 : // New try with _BLOCK for hor and ver after completely
758 : // supporting full width for vertical text.
759 9 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
760 : {
761 7 : rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
762 : }
763 :
764 9 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
765 : {
766 0 : rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
767 : }
768 : }
769 :
770 9 : rOutliner.SetPaperSize(aNullSize);
771 9 : if (bContourFrame)
772 0 : ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth );
773 :
774 : // put text into the outliner, if available from the edit outliner
775 9 : SdrText* pText = getActiveText();
776 9 : OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
777 9 : OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject;
778 :
779 9 : if (pPara)
780 : {
781 9 : bool bHitTest = false;
782 9 : if( pModel )
783 9 : bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
784 :
785 9 : const SdrTextObj* pTestObj = rOutliner.GetTextObj();
786 9 : if( !pTestObj || !bHitTest || pTestObj != this ||
787 0 : pTestObj->GetOutlinerParaObject() != pOutlinerParaObject )
788 : {
789 9 : if( bHitTest ) // #i33696# take back fix #i27510#
790 : {
791 0 : rOutliner.SetTextObj( this );
792 0 : rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
793 : }
794 :
795 9 : rOutliner.SetUpdateMode(true);
796 9 : rOutliner.SetText(*pPara);
797 : }
798 : }
799 : else
800 : {
801 0 : rOutliner.SetTextObj( NULL );
802 : }
803 :
804 9 : if (pEdtOutl && !bNoEditText && pPara)
805 0 : delete pPara;
806 :
807 9 : rOutliner.SetUpdateMode(true);
808 9 : rOutliner.SetControlWord(nStat0);
809 :
810 9 : if( pText )
811 9 : pText->CheckPortionInfo(rOutliner);
812 :
813 9 : Point aTextPos(aAnkRect.TopLeft());
814 9 : Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
815 :
816 : // For draw objects containing text correct hor/ver alignment if text is bigger
817 : // than the object itself. Without that correction, the text would always be
818 : // formatted to the left edge (or top edge when vertical) of the draw object.
819 9 : if(!IsTextFrame())
820 : {
821 2 : if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
822 : {
823 : // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
824 : // else the alignment is wanted.
825 0 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
826 : {
827 0 : eHAdj = SDRTEXTHORZADJUST_CENTER;
828 : }
829 : }
830 :
831 2 : if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
832 : {
833 : // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
834 : // else the alignment is wanted.
835 0 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
836 : {
837 0 : eVAdj = SDRTEXTVERTADJUST_CENTER;
838 : }
839 : }
840 : }
841 :
842 9 : if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
843 : {
844 2 : long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
845 2 : if (eHAdj==SDRTEXTHORZADJUST_CENTER)
846 2 : aTextPos.X()+=nFreeWdt/2;
847 2 : if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
848 0 : aTextPos.X()+=nFreeWdt;
849 : }
850 9 : if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
851 : {
852 8 : long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
853 8 : if (eVAdj==SDRTEXTVERTADJUST_CENTER)
854 8 : aTextPos.Y()+=nFreeHgt/2;
855 8 : if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
856 0 : aTextPos.Y()+=nFreeHgt;
857 : }
858 9 : if (aGeo.nRotationAngle!=0)
859 0 : RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
860 :
861 9 : if (pAnchorRect)
862 9 : *pAnchorRect=aAnkRect;
863 :
864 : // rTextRect might not be correct in some cases at ContourFrame
865 9 : rTextRect=Rectangle(aTextPos,aTextSiz);
866 9 : if (bContourFrame)
867 0 : rTextRect=aAnkRect;
868 9 : }
869 :
870 31883 : OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const
871 : {
872 31883 : OutlinerParaObject* pPara=NULL;
873 31883 : if( HasTextImpl( pEdtOutl ) )
874 : {
875 44 : sal_Int32 nParaCount = pEdtOutl->GetParagraphCount();
876 44 : pPara = pEdtOutl->CreateParaObject(0, nParaCount);
877 : }
878 31883 : return pPara;
879 : }
880 :
881 0 : void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg)
882 : {
883 0 : OutputDevice* pOut = rOutliner.GetRefDevice();
884 0 : bool bNoStretching(false);
885 :
886 0 : if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER)
887 : {
888 : // check whether CharStretching is possible at all
889 0 : GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
890 0 : OUString aTestString(static_cast<sal_Unicode>('J'));
891 :
892 0 : if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause()))
893 0 : pMtf = NULL;
894 :
895 0 : if(pMtf)
896 0 : pMtf->Pause(true);
897 :
898 0 : vcl::Font aFontMerk(pOut->GetFont());
899 0 : vcl::Font aTmpFont( OutputDevice::GetDefaultFont( DefaultFontType::SERIF, LANGUAGE_SYSTEM, GetDefaultFontFlags::OnlyOne ) );
900 :
901 0 : aTmpFont.SetSize(Size(0,100));
902 0 : pOut->SetFont(aTmpFont);
903 0 : Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
904 0 : aTmpFont.SetSize(Size(800,100));
905 0 : pOut->SetFont(aTmpFont);
906 0 : Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
907 0 : pOut->SetFont(aFontMerk);
908 :
909 0 : if(pMtf)
910 0 : pMtf->Pause(false);
911 :
912 0 : bNoStretching = (aSize1 == aSize2);
913 :
914 : #ifdef WNT
915 : // Windows zooms the font proportionally when using Size(100,500),
916 : // we don't like that.
917 : if(aSize2.Height() >= aSize1.Height() * 2)
918 : {
919 : bNoStretching = true;
920 : }
921 : #endif
922 : }
923 0 : unsigned nLoopCount=0;
924 0 : bool bNoMoreLoop = false;
925 0 : long nXDiff0=0x7FFFFFFF;
926 0 : long nWantWdt=rShapeSize.Width();
927 0 : long nIsWdt=rTextSize.Width();
928 0 : if (nIsWdt==0) nIsWdt=1;
929 :
930 0 : long nWantHgt=rShapeSize.Height();
931 0 : long nIsHgt=rTextSize.Height();
932 0 : if (nIsHgt==0) nIsHgt=1;
933 :
934 0 : long nXTolPl=nWantWdt/100; // tolerance: +1%
935 0 : long nXTolMi=nWantWdt/25; // tolerance: -4%
936 0 : long nXKorr =nWantWdt/20; // correction scale: 5%
937 :
938 0 : long nX=(nWantWdt*100) /nIsWdt; // calculate X stretching
939 0 : long nY=(nWantHgt*100) /nIsHgt; // calculate Y stretching
940 0 : bool bChkX = true;
941 0 : if (bNoStretching) { // might only be possible proportionally
942 0 : if (nX>nY) { nX=nY; bChkX=false; }
943 0 : else { nY=nX; }
944 : }
945 :
946 0 : while (nLoopCount<5 && !bNoMoreLoop) {
947 0 : if (nX<0) nX=-nX;
948 0 : if (nX<1) { nX=1; bNoMoreLoop = true; }
949 0 : if (nX>65535) { nX=65535; bNoMoreLoop = true; }
950 :
951 0 : if (nY<0) nY=-nY;
952 0 : if (nY<1) { nY=1; bNoMoreLoop = true; }
953 0 : if (nY>65535) { nY=65535; bNoMoreLoop = true; }
954 :
955 : // exception, there is no text yet (horizontal case)
956 0 : if(nIsWdt <= 1)
957 : {
958 0 : nX = nY;
959 0 : bNoMoreLoop = true;
960 : }
961 :
962 : // exception, there is no text yet (vertical case)
963 0 : if(nIsHgt <= 1)
964 : {
965 0 : nY = nX;
966 0 : bNoMoreLoop = true;
967 : }
968 :
969 0 : rOutliner.SetGlobalCharStretching((sal_uInt16)nX,(sal_uInt16)nY);
970 0 : nLoopCount++;
971 0 : Size aSiz(rOutliner.CalcTextSize());
972 0 : long nXDiff=aSiz.Width()-nWantWdt;
973 0 : rFitXKorreg=Fraction(nWantWdt,aSiz.Width());
974 0 : if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0) {
975 0 : bNoMoreLoop = true;
976 : } else {
977 : // correct stretching factors
978 0 : long nMul=nWantWdt;
979 0 : long nDiv=aSiz.Width();
980 0 : if (std::abs(nXDiff)<=2*nXKorr) {
981 0 : if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // but only add half of what we calculated,
982 0 : else nMul+=(nDiv-nMul)/2; // because the EditEngine calculates wrongly later on
983 : }
984 0 : nX=nX*nMul/nDiv;
985 0 : if (bNoStretching) nY=nX;
986 : }
987 0 : nXDiff0=nXDiff;
988 : }
989 0 : }
990 :
991 2081 : OUString SdrTextObj::TakeObjNameSingul() const
992 : {
993 2081 : OUString aStr;
994 :
995 2081 : switch(eTextKind)
996 : {
997 : case OBJ_OUTLINETEXT:
998 : {
999 447 : aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT);
1000 447 : break;
1001 : }
1002 :
1003 : case OBJ_TITLETEXT :
1004 : {
1005 552 : aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT);
1006 552 : break;
1007 : }
1008 :
1009 : default:
1010 : {
1011 1082 : if(IsLinkedText())
1012 0 : aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK);
1013 : else
1014 1082 : aStr = ImpGetResStr(STR_ObjNameSingulTEXT);
1015 1082 : break;
1016 : }
1017 : }
1018 :
1019 2081 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1020 2081 : if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT)
1021 : {
1022 : // shouldn't currently cause any problems at OUTLINETEXT
1023 1634 : OUString aStr2(comphelper::string::stripStart(pOutlinerParaObject->GetTextObject().GetText(0), ' '));
1024 :
1025 : // avoid non expanded text portions in object name
1026 : // (second condition is new)
1027 1634 : if(!aStr2.isEmpty() && aStr2.indexOf(sal_Unicode(255)) == -1)
1028 : {
1029 : // space between ResStr and content text
1030 1634 : aStr += " ";
1031 :
1032 1634 : aStr += "\'";
1033 :
1034 1634 : if(aStr2.getLength() > 10)
1035 : {
1036 817 : aStr2 = aStr2.copy(0, 8);
1037 817 : aStr2 += "...";
1038 : }
1039 :
1040 1634 : aStr += aStr2;
1041 1634 : aStr += "\'";
1042 1634 : }
1043 : }
1044 :
1045 2081 : OUStringBuffer sName(aStr);
1046 :
1047 4162 : OUString aName(GetName());
1048 2081 : if (!aName.isEmpty())
1049 : {
1050 0 : sName.append(' ');
1051 0 : sName.append('\'');
1052 0 : sName.append(aName);
1053 0 : sName.append('\'');
1054 : }
1055 :
1056 4162 : return sName.makeStringAndClear();
1057 : }
1058 :
1059 0 : OUString SdrTextObj::TakeObjNamePlural() const
1060 : {
1061 0 : OUString sName;
1062 0 : switch (eTextKind) {
1063 0 : case OBJ_OUTLINETEXT: sName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break;
1064 0 : case OBJ_TITLETEXT : sName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break;
1065 : default: {
1066 0 : if (IsLinkedText()) {
1067 0 : sName=ImpGetResStr(STR_ObjNamePluralTEXTLNK);
1068 : } else {
1069 0 : sName=ImpGetResStr(STR_ObjNamePluralTEXT);
1070 : }
1071 0 : } break;
1072 : } // switch
1073 0 : return sName;
1074 : }
1075 :
1076 0 : SdrTextObj* SdrTextObj::Clone() const
1077 : {
1078 0 : return CloneHelper< SdrTextObj >();
1079 : }
1080 :
1081 705 : SdrTextObj& SdrTextObj::operator=(const SdrTextObj& rObj)
1082 : {
1083 705 : if( this == &rObj )
1084 0 : return *this;
1085 : // call parent
1086 705 : SdrObject::operator=(rObj);
1087 :
1088 705 : maRect = rObj.maRect;
1089 705 : aGeo =rObj.aGeo;
1090 705 : eTextKind =rObj.eTextKind;
1091 705 : bTextFrame=rObj.bTextFrame;
1092 705 : aTextSize=rObj.aTextSize;
1093 705 : bTextSizeDirty=rObj.bTextSizeDirty;
1094 :
1095 : // Not all of the necessary parameters were copied yet.
1096 705 : bNoShear = rObj.bNoShear;
1097 705 : bNoRotate = rObj.bNoRotate;
1098 705 : bNoMirror = rObj.bNoMirror;
1099 705 : bDisableAutoWidthOnDragging = rObj.bDisableAutoWidthOnDragging;
1100 :
1101 705 : OutlinerParaObject* pNewOutlinerParaObject = 0;
1102 :
1103 705 : SdrText* pText = getActiveText();
1104 :
1105 705 : if( pText && rObj.HasText() )
1106 : {
1107 53 : const Outliner* pEO=rObj.pEdtOutl;
1108 53 : if (pEO!=NULL)
1109 : {
1110 0 : pNewOutlinerParaObject = pEO->CreateParaObject();
1111 : }
1112 : else
1113 : {
1114 53 : pNewOutlinerParaObject = new OutlinerParaObject(*rObj.getActiveText()->GetOutlinerParaObject());
1115 : }
1116 : }
1117 :
1118 705 : mpText->SetOutlinerParaObject( pNewOutlinerParaObject );
1119 705 : ImpSetTextStyleSheetListeners();
1120 705 : return *this;
1121 : }
1122 :
1123 0 : basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() const
1124 : {
1125 0 : Polygon aPol(maRect);
1126 0 : if (aGeo.nShearAngle!=0) ShearPoly(aPol,maRect.TopLeft(),aGeo.nTan);
1127 0 : if (aGeo.nRotationAngle!=0) RotatePoly(aPol,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1128 :
1129 0 : basegfx::B2DPolyPolygon aRetval;
1130 0 : aRetval.append(aPol.getB2DPolygon());
1131 0 : return aRetval;
1132 : }
1133 :
1134 9 : basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const
1135 : {
1136 9 : basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour());
1137 :
1138 : // and now add the BoundRect of the text, if necessary
1139 9 : if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1140 : {
1141 : // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1142 : // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1143 : // in every case
1144 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
1145 :
1146 0 : Rectangle aAnchor2;
1147 0 : Rectangle aR;
1148 0 : TakeTextRect(rOutliner,aR,false,&aAnchor2);
1149 0 : rOutliner.Clear();
1150 0 : bool bFitToSize(IsFitToSize());
1151 0 : if (bFitToSize) aR=aAnchor2;
1152 0 : Polygon aPol(aR);
1153 0 : if (aGeo.nRotationAngle!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos);
1154 :
1155 0 : aRetval.append(aPol.getB2DPolygon());
1156 : }
1157 :
1158 9 : return aRetval;
1159 : }
1160 :
1161 59985 : void SdrTextObj::RecalcSnapRect()
1162 : {
1163 59985 : if (aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0)
1164 : {
1165 1225 : Polygon aPol(maRect);
1166 1225 : if (aGeo.nShearAngle!=0) ShearPoly(aPol,maRect.TopLeft(),aGeo.nTan);
1167 1225 : if (aGeo.nRotationAngle!=0) RotatePoly(aPol,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1168 1225 : maSnapRect=aPol.GetBoundRect();
1169 : } else {
1170 58760 : maSnapRect = maRect;
1171 : }
1172 59985 : }
1173 :
1174 0 : sal_uInt32 SdrTextObj::GetSnapPointCount() const
1175 : {
1176 0 : return 4L;
1177 : }
1178 :
1179 0 : Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const
1180 : {
1181 0 : Point aP;
1182 0 : switch (i) {
1183 0 : case 0: aP=maRect.TopLeft(); break;
1184 0 : case 1: aP=maRect.TopRight(); break;
1185 0 : case 2: aP=maRect.BottomLeft(); break;
1186 0 : case 3: aP=maRect.BottomRight(); break;
1187 0 : default: aP=maRect.Center(); break;
1188 : }
1189 0 : if (aGeo.nShearAngle!=0) ShearPoint(aP,maRect.TopLeft(),aGeo.nTan);
1190 0 : if (aGeo.nRotationAngle!=0) RotatePoint(aP,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1191 0 : return aP;
1192 : }
1193 :
1194 104420 : void SdrTextObj::ImpCheckMasterCachable()
1195 : {
1196 104420 : bNotMasterCachable=false;
1197 :
1198 104420 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1199 :
1200 104420 : if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() )
1201 : {
1202 97516 : const EditTextObject& rText= pOutlinerParaObject->GetTextObject();
1203 97516 : bNotMasterCachable=rText.HasField(SvxPageField::StaticClassId());
1204 97516 : if( !bNotMasterCachable )
1205 : {
1206 95116 : bNotMasterCachable=rText.HasField(SvxHeaderField::StaticClassId());
1207 95116 : if( !bNotMasterCachable )
1208 : {
1209 93776 : bNotMasterCachable=rText.HasField(SvxFooterField::StaticClassId());
1210 93776 : if( !bNotMasterCachable )
1211 : {
1212 91481 : bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticClassId());
1213 : }
1214 : }
1215 : }
1216 : }
1217 104420 : }
1218 :
1219 : // Extracted from ImpGetDrawOutliner()
1220 294660 : void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const
1221 : {
1222 294660 : rOutl.SetUpdateMode(false);
1223 294660 : sal_uInt16 nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT;
1224 294660 : if ( !IsOutlText() )
1225 273805 : nOutlinerMode = OUTLINERMODE_TEXTOBJECT;
1226 294660 : rOutl.Init( nOutlinerMode );
1227 :
1228 294660 : rOutl.SetGlobalCharStretching(100,100);
1229 294660 : EEControlBits nStat=rOutl.GetControlWord();
1230 294660 : nStat &= ~EEControlBits(EEControlBits::STRETCHING|EEControlBits::AUTOPAGESIZE);
1231 294660 : rOutl.SetControlWord(nStat);
1232 294660 : Size aNullSize;
1233 294660 : Size aMaxSize(100000,100000);
1234 294660 : rOutl.SetMinAutoPaperSize(aNullSize);
1235 294660 : rOutl.SetMaxAutoPaperSize(aMaxSize);
1236 294660 : rOutl.SetPaperSize(aMaxSize);
1237 294660 : rOutl.ClearPolygon();
1238 294660 : }
1239 :
1240 294660 : SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const
1241 : {
1242 294660 : SdrOutliner& rOutl=pModel->GetDrawOutliner(this);
1243 :
1244 : // Code extracted to ImpInitDrawOutliner()
1245 294660 : ImpInitDrawOutliner( rOutl );
1246 :
1247 294660 : return rOutl;
1248 : }
1249 :
1250 : // Extracted from Paint()
1251 0 : void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame,
1252 : SdrOutliner& rOutliner,
1253 : Rectangle& rTextRect,
1254 : Rectangle& rAnchorRect,
1255 : Rectangle& rPaintRect,
1256 : Fraction& rFitXKorreg ) const
1257 : {
1258 0 : if (!bContourFrame)
1259 : {
1260 : // FitToSize can't be used together with ContourFrame for now
1261 0 : if (IsFitToSize() || IsAutoFit())
1262 : {
1263 0 : EEControlBits nStat=rOutliner.GetControlWord();
1264 0 : nStat|=EEControlBits::STRETCHING|EEControlBits::AUTOPAGESIZE;
1265 0 : rOutliner.SetControlWord(nStat);
1266 : }
1267 : }
1268 0 : rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
1269 0 : TakeTextRect(rOutliner, rTextRect, false, &rAnchorRect);
1270 0 : rPaintRect = rTextRect;
1271 :
1272 0 : if (!bContourFrame)
1273 : {
1274 : // FitToSize can't be used together with ContourFrame for now
1275 0 : if (IsFitToSize())
1276 : {
1277 0 : ImpSetCharStretching(rOutliner,rTextRect.GetSize(),rAnchorRect.GetSize(),rFitXKorreg);
1278 0 : rPaintRect=rAnchorRect;
1279 : }
1280 0 : else if (IsAutoFit())
1281 : {
1282 0 : ImpAutoFitText(rOutliner);
1283 : }
1284 : }
1285 0 : }
1286 :
1287 3 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
1288 : {
1289 3 : const Size aShapeSize=GetSnapRect().GetSize();
1290 : ImpAutoFitText( rOutliner,
1291 3 : Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
1292 3 : aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
1293 9 : IsVerticalWriting() );
1294 3 : }
1295 :
1296 74 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
1297 : {
1298 : // EditEngine formatting is unstable enough for
1299 : // line-breaking text that we need some more samples
1300 :
1301 : // loop early-exits if we detect an already attained value
1302 74 : sal_uInt16 nMinStretchX=0, nMinStretchY=0;
1303 74 : sal_uInt16 aOldStretchXVals[]={0,0,0,0,0,0,0,0,0,0};
1304 74 : const size_t aStretchArySize=SAL_N_ELEMENTS(aOldStretchXVals);
1305 148 : for(unsigned int i=0; i<aStretchArySize; ++i)
1306 : {
1307 148 : const Size aCurrTextSize = rOutliner.CalcTextSizeNTP();
1308 148 : double fFactor(1.0);
1309 148 : if( bIsVerticalWriting )
1310 : {
1311 0 : if (aCurrTextSize.Width() != 0)
1312 : {
1313 0 : fFactor = double(rTextSize.Width())/aCurrTextSize.Width();
1314 : }
1315 : }
1316 148 : else if (aCurrTextSize.Height() != 0)
1317 : {
1318 146 : fFactor = double(rTextSize.Height())/aCurrTextSize.Height();
1319 : }
1320 : // fFactor scales in both x and y directions
1321 : // - this is fine for bulleted words
1322 : // - but it scales too much for a long paragraph
1323 : // - taking sqrt scales long paragraphs the best
1324 : // - bulleted words will have to go through more iterations
1325 148 : fFactor = std::sqrt(fFactor);
1326 :
1327 : sal_uInt16 nCurrStretchX, nCurrStretchY;
1328 148 : rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY);
1329 :
1330 148 : if (fFactor >= 1.0 )
1331 : {
1332 : // resulting text area fits into available shape rect -
1333 : // err on the larger stretching, to optimally fill area
1334 148 : nMinStretchX = std::max(nMinStretchX,nCurrStretchX);
1335 148 : nMinStretchY = std::max(nMinStretchY,nCurrStretchY);
1336 : }
1337 :
1338 148 : aOldStretchXVals[i] = nCurrStretchX;
1339 148 : if( std::find(aOldStretchXVals, aOldStretchXVals+i, nCurrStretchX) != aOldStretchXVals+i )
1340 74 : break; // same value already attained once; algo is looping, exit
1341 :
1342 74 : if (fFactor < 1.0 || (fFactor >= 1.0 && nCurrStretchX != 100))
1343 : {
1344 0 : nCurrStretchX = sal::static_int_cast<sal_uInt16>(nCurrStretchX*fFactor);
1345 0 : nCurrStretchY = sal::static_int_cast<sal_uInt16>(nCurrStretchY*fFactor);
1346 0 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nCurrStretchX),
1347 0 : std::min(sal_uInt16(100),nCurrStretchY));
1348 : OSL_TRACE("SdrTextObj::onEditOutlinerStatusEvent(): zoom is %d", nCurrStretchX);
1349 : }
1350 : }
1351 :
1352 : OSL_TRACE("---- SdrTextObj::onEditOutlinerStatusEvent(): final zoom is %d ----", nMinStretchX);
1353 148 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX),
1354 222 : std::min(sal_uInt16(100),nMinStretchY));
1355 74 : }
1356 :
1357 0 : void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1358 : {
1359 0 : ImpInitDrawOutliner( rOutl );
1360 0 : UpdateOutlinerFormatting( rOutl, rPaintRect );
1361 0 : }
1362 :
1363 0 : void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1364 : {
1365 0 : Rectangle aTextRect;
1366 0 : Rectangle aAnchorRect;
1367 0 : Fraction aFitXKorreg(1,1);
1368 :
1369 0 : bool bContourFrame=IsContourTextFrame();
1370 :
1371 0 : if( GetModel() )
1372 : {
1373 : MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0),
1374 0 : GetModel()->GetScaleFraction(),
1375 0 : GetModel()->GetScaleFraction());
1376 0 : rOutl.SetRefMapMode(aMapMode);
1377 : }
1378 :
1379 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg );
1380 0 : }
1381 :
1382 :
1383 :
1384 621154 : OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const
1385 : {
1386 621154 : SdrText* pText = getActiveText();
1387 621154 : if( pText )
1388 621154 : return pText->GetOutlinerParaObject();
1389 : else
1390 0 : return 0;
1391 : }
1392 :
1393 6696 : void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
1394 : {
1395 6696 : NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() );
1396 6696 : }
1397 :
1398 104420 : void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText )
1399 : {
1400 104420 : if( pText )
1401 103882 : pText->SetOutlinerParaObject( pTextObject );
1402 :
1403 104420 : if (pText && pText->GetOutlinerParaObject())
1404 : {
1405 103231 : SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical()
1406 : ? com::sun::star::text::WritingMode_TB_RL
1407 : : com::sun::star::text::WritingMode_LR_TB,
1408 103231 : SDRATTR_TEXTDIRECTION);
1409 103231 : GetProperties().SetObjectItemDirect(aWritingMode);
1410 : }
1411 :
1412 104420 : SetTextSizeDirty();
1413 104420 : if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth()))
1414 : { // adapt text frame!
1415 88740 : NbcAdjustTextFrameWidthAndHeight();
1416 : }
1417 104420 : if (!IsTextFrame())
1418 : {
1419 : // the SnapRect keeps its size
1420 3564 : SetRectsDirty(true);
1421 : }
1422 :
1423 : // always invalidate BoundRect on change
1424 104420 : SetBoundRectDirty();
1425 104420 : ActionChanged();
1426 :
1427 104420 : ImpSetTextStyleSheetListeners();
1428 104420 : ImpCheckMasterCachable();
1429 104420 : }
1430 :
1431 149 : void SdrTextObj::NbcReformatText()
1432 : {
1433 149 : SdrText* pText = getActiveText();
1434 149 : if( pText && pText->GetOutlinerParaObject() )
1435 : {
1436 21 : pText->ReformatText();
1437 21 : if (bTextFrame)
1438 : {
1439 9 : NbcAdjustTextFrameWidthAndHeight();
1440 : }
1441 : else
1442 : {
1443 : // the SnapRect keeps its size
1444 12 : SetBoundRectDirty();
1445 12 : SetRectsDirty(true);
1446 : }
1447 21 : SetTextSizeDirty();
1448 21 : ActionChanged();
1449 : // i22396
1450 : // Necessary here since we have no compare operator at the outliner
1451 : // para object which may detect changes regarding the combination
1452 : // of outliner para data and configuration (e.g., change of
1453 : // formatting of text numerals)
1454 21 : GetViewContact().flushViewObjectContacts(false);
1455 : }
1456 149 : }
1457 :
1458 0 : void SdrTextObj::ReformatText()
1459 : {
1460 0 : if(GetOutlinerParaObject())
1461 : {
1462 0 : Rectangle aBoundRect0;
1463 0 : if (pUserCall!=NULL)
1464 0 : aBoundRect0=GetLastBoundRect();
1465 :
1466 0 : NbcReformatText();
1467 0 : SetChanged();
1468 0 : BroadcastObjectChange();
1469 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1470 : }
1471 0 : }
1472 :
1473 10 : SdrObjGeoData* SdrTextObj::NewGeoData() const
1474 : {
1475 10 : return new SdrTextObjGeoData;
1476 : }
1477 :
1478 1363 : void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const
1479 : {
1480 1363 : SdrAttrObj::SaveGeoData(rGeo);
1481 1363 : SdrTextObjGeoData& rTGeo=static_cast<SdrTextObjGeoData&>(rGeo);
1482 1363 : rTGeo.aRect = maRect;
1483 1363 : rTGeo.aGeo =aGeo;
1484 1363 : }
1485 :
1486 1 : void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo)
1487 : { // RectsDirty is called by SdrObject
1488 1 : SdrAttrObj::RestGeoData(rGeo);
1489 1 : const SdrTextObjGeoData& rTGeo=static_cast<const SdrTextObjGeoData&>(rGeo);
1490 1 : NbcSetLogicRect(rTGeo.aRect);
1491 1 : aGeo =rTGeo.aGeo;
1492 1 : SetTextSizeDirty();
1493 1 : }
1494 :
1495 256275 : SdrFitToSizeType SdrTextObj::GetFitToSize() const
1496 : {
1497 256275 : SdrFitToSizeType eType = SDRTEXTFIT_NONE;
1498 :
1499 256275 : if(!IsAutoGrowWidth())
1500 151501 : eType = static_cast<const SdrTextFitToSizeTypeItem&>(GetObjectItem(SDRATTR_TEXT_FITTOSIZE)).GetValue();
1501 :
1502 256275 : return eType;
1503 : }
1504 :
1505 68005 : const Rectangle& SdrTextObj::GetGeoRect() const
1506 : {
1507 68005 : return maRect;
1508 : }
1509 :
1510 3287 : void SdrTextObj::ForceOutlinerParaObject()
1511 : {
1512 3287 : SdrText* pText = getActiveText();
1513 3287 : if( pText && (pText->GetOutlinerParaObject() == 0) )
1514 : {
1515 302 : sal_uInt16 nOutlMode = OUTLINERMODE_TEXTOBJECT;
1516 302 : if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT )
1517 0 : nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
1518 :
1519 302 : pText->ForceOutlinerParaObject( nOutlMode );
1520 : }
1521 3287 : }
1522 :
1523 100757 : bool SdrTextObj::IsVerticalWriting() const
1524 : {
1525 100757 : if(pEdtOutl)
1526 : {
1527 49 : return pEdtOutl->IsVertical();
1528 : }
1529 :
1530 100708 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1531 100708 : if(pOutlinerParaObject)
1532 : {
1533 68480 : return pOutlinerParaObject->IsVertical();
1534 : }
1535 :
1536 32228 : return false;
1537 : }
1538 :
1539 122478 : void SdrTextObj::SetVerticalWriting(bool bVertical)
1540 : {
1541 122478 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1542 122478 : if( !pOutlinerParaObject && bVertical )
1543 : {
1544 : // we only need to force a outliner para object if the default of
1545 : // horizontal text is changed
1546 0 : ForceOutlinerParaObject();
1547 0 : pOutlinerParaObject = GetOutlinerParaObject();
1548 : }
1549 :
1550 122478 : if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != (bool)bVertical) )
1551 : {
1552 : // get item settings
1553 2 : const SfxItemSet& rSet = GetObjectItemSet();
1554 2 : bool bAutoGrowWidth = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
1555 2 : bool bAutoGrowHeight = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
1556 :
1557 : // Also exchange hor/ver adjust items
1558 2 : SdrTextHorzAdjust eHorz = static_cast<const SdrTextHorzAdjustItem&>(rSet.Get(SDRATTR_TEXT_HORZADJUST)).GetValue();
1559 2 : SdrTextVertAdjust eVert = static_cast<const SdrTextVertAdjustItem&>(rSet.Get(SDRATTR_TEXT_VERTADJUST)).GetValue();
1560 :
1561 : // rescue object size
1562 2 : Rectangle aObjectRect = GetSnapRect();
1563 :
1564 : // prepare ItemSet to set exchanged width and height items
1565 2 : SfxItemSet aNewSet(*rSet.GetPool(),
1566 : SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
1567 : // Expanded item ranges to also support hor and ver adjust.
1568 : SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
1569 : SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
1570 2 : 0, 0);
1571 :
1572 2 : aNewSet.Put(rSet);
1573 2 : aNewSet.Put(makeSdrTextAutoGrowWidthItem(bAutoGrowHeight));
1574 2 : aNewSet.Put(makeSdrTextAutoGrowHeightItem(bAutoGrowWidth));
1575 :
1576 : // Exchange horz and vert adjusts
1577 2 : switch(eVert)
1578 : {
1579 2 : case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
1580 0 : case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
1581 0 : case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
1582 0 : case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
1583 : }
1584 2 : switch(eHorz)
1585 : {
1586 0 : case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
1587 0 : case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
1588 2 : case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
1589 0 : case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
1590 : }
1591 :
1592 2 : SetObjectItemSet(aNewSet);
1593 :
1594 2 : pOutlinerParaObject = GetOutlinerParaObject();
1595 2 : if( pOutlinerParaObject )
1596 : {
1597 : // set ParaObject orientation accordingly
1598 2 : pOutlinerParaObject->SetVertical(bVertical);
1599 : }
1600 :
1601 : // restore object size
1602 2 : SetSnapRect(aObjectRect);
1603 : }
1604 122478 : }
1605 :
1606 :
1607 :
1608 : // transformation interface for StarOfficeAPI. This implements support for
1609 : // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1610 : // moment it contains a shearX, rotation and translation, but for setting all linear
1611 : // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1612 :
1613 :
1614 : // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1615 : // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1616 33390 : bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
1617 : {
1618 : // get turn and shear
1619 33390 : double fRotate = (aGeo.nRotationAngle / 100.0) * F_PI180;
1620 33390 : double fShearX = (aGeo.nShearAngle / 100.0) * F_PI180;
1621 :
1622 : // get aRect, this is the unrotated snaprect
1623 33390 : Rectangle aRectangle(maRect);
1624 :
1625 : // fill other values
1626 33390 : basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
1627 66780 : basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
1628 :
1629 : // position maybe relative to anchorpos, convert
1630 33390 : if( pModel && pModel->IsWriter() )
1631 : {
1632 669 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1633 : {
1634 168 : aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1635 : }
1636 : }
1637 :
1638 : // force MapUnit to 100th mm
1639 33390 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1640 33390 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1641 : {
1642 669 : switch(eMapUnit)
1643 : {
1644 : case SFX_MAPUNIT_TWIP :
1645 : {
1646 : // position
1647 669 : aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1648 669 : aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1649 :
1650 : // size
1651 669 : aScale.setX(ImplTwipsToMM(aScale.getX()));
1652 669 : aScale.setY(ImplTwipsToMM(aScale.getY()));
1653 :
1654 669 : break;
1655 : }
1656 : default:
1657 : {
1658 : OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1659 : }
1660 : }
1661 : }
1662 :
1663 : // build matrix
1664 100170 : rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
1665 : aScale,
1666 33390 : basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
1667 33390 : basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
1668 33390 : aTranslate);
1669 :
1670 66780 : return false;
1671 : }
1672 :
1673 : // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1674 : // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1675 : // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1676 32936 : void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
1677 : {
1678 : // break up matrix
1679 32936 : basegfx::B2DTuple aScale;
1680 65872 : basegfx::B2DTuple aTranslate;
1681 32936 : double fRotate(0.0);
1682 32936 : double fShearX(0.0);
1683 32936 : rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1684 :
1685 : // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
1686 : // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
1687 32936 : if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
1688 : {
1689 0 : aScale.setX(fabs(aScale.getX()));
1690 0 : aScale.setY(fabs(aScale.getY()));
1691 0 : fRotate = fmod(fRotate + F_PI, F_2PI);
1692 : }
1693 :
1694 : // reset object shear and rotations
1695 32936 : aGeo.nRotationAngle = 0;
1696 32936 : aGeo.RecalcSinCos();
1697 32936 : aGeo.nShearAngle = 0;
1698 32936 : aGeo.RecalcTan();
1699 :
1700 : // force metric to pool metric
1701 32936 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1702 32936 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1703 : {
1704 476 : switch(eMapUnit)
1705 : {
1706 : case SFX_MAPUNIT_TWIP :
1707 : {
1708 : // position
1709 476 : aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
1710 476 : aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
1711 :
1712 : // size
1713 476 : aScale.setX(ImplMMToTwips(aScale.getX()));
1714 476 : aScale.setY(ImplMMToTwips(aScale.getY()));
1715 :
1716 476 : break;
1717 : }
1718 : default:
1719 : {
1720 : OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1721 : }
1722 : }
1723 : }
1724 :
1725 : // if anchor is used, make position relative to it
1726 32936 : if( pModel && pModel->IsWriter() )
1727 : {
1728 476 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1729 : {
1730 0 : aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1731 : }
1732 : }
1733 :
1734 : // build and set BaseRect (use scale)
1735 32936 : Point aPoint = Point();
1736 32936 : Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
1737 32936 : Rectangle aBaseRect(aPoint, aSize);
1738 32936 : SetSnapRect(aBaseRect);
1739 :
1740 : // shear?
1741 32936 : if(!basegfx::fTools::equalZero(fShearX))
1742 : {
1743 0 : GeoStat aGeoStat;
1744 0 : aGeoStat.nShearAngle = FRound((atan(fShearX) / F_PI180) * 100.0);
1745 0 : aGeoStat.RecalcTan();
1746 0 : Shear(Point(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
1747 : }
1748 :
1749 : // rotation?
1750 32936 : if(!basegfx::fTools::equalZero(fRotate))
1751 : {
1752 1172 : GeoStat aGeoStat;
1753 :
1754 : // #i78696#
1755 : // fRotate is matematically correct, but aGeoStat.nRotationAngle is
1756 : // mirrored -> mirror value here
1757 1172 : aGeoStat.nRotationAngle = NormAngle360(FRound(-fRotate / F_PI18000));
1758 1172 : aGeoStat.RecalcSinCos();
1759 1172 : Rotate(Point(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
1760 : }
1761 :
1762 : // translate?
1763 32936 : if(!aTranslate.equalZero())
1764 : {
1765 31559 : Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
1766 32936 : }
1767 32936 : }
1768 :
1769 0 : bool SdrTextObj::IsReallyEdited() const
1770 : {
1771 0 : return pEdtOutl && pEdtOutl->IsModified();
1772 : }
1773 :
1774 : // moved inlines here form hxx
1775 :
1776 50607 : long SdrTextObj::GetEckenradius() const
1777 : {
1778 50607 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS)).GetValue();
1779 : }
1780 :
1781 134126 : long SdrTextObj::GetMinTextFrameHeight() const
1782 : {
1783 134126 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT)).GetValue();
1784 : }
1785 :
1786 134126 : long SdrTextObj::GetMaxTextFrameHeight() const
1787 : {
1788 134126 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT)).GetValue();
1789 : }
1790 :
1791 57497 : long SdrTextObj::GetMinTextFrameWidth() const
1792 : {
1793 57497 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH)).GetValue();
1794 : }
1795 :
1796 57497 : long SdrTextObj::GetMaxTextFrameWidth() const
1797 : {
1798 57497 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH)).GetValue();
1799 : }
1800 :
1801 1044 : bool SdrTextObj::IsFontwork() const
1802 : {
1803 1044 : return !bTextFrame // Default is FALSE
1804 1044 : && static_cast<const XFormTextStyleItem&>(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE)).GetValue() != XFT_NONE;
1805 : }
1806 :
1807 35 : bool SdrTextObj::IsHideContour() const
1808 : {
1809 35 : return !bTextFrame // Default is: no, don't HideContour; HideContour not together with TextFrames
1810 35 : && static_cast<const XFormTextHideFormItem&>(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM)).GetValue();
1811 : }
1812 :
1813 219861 : bool SdrTextObj::IsContourTextFrame() const
1814 : {
1815 219861 : return !bTextFrame // ContourFrame not together with normal TextFrames
1816 219861 : && static_cast<const SdrOnOffItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME)).GetValue();
1817 : }
1818 :
1819 300593 : long SdrTextObj::GetTextLeftDistance() const
1820 : {
1821 300593 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST)).GetValue();
1822 : }
1823 :
1824 300593 : long SdrTextObj::GetTextRightDistance() const
1825 : {
1826 300593 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST)).GetValue();
1827 : }
1828 :
1829 332974 : long SdrTextObj::GetTextUpperDistance() const
1830 : {
1831 332974 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST)).GetValue();
1832 : }
1833 :
1834 332974 : long SdrTextObj::GetTextLowerDistance() const
1835 : {
1836 332974 : return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST)).GetValue();
1837 : }
1838 :
1839 1205808 : SdrTextAniKind SdrTextObj::GetTextAniKind() const
1840 : {
1841 1205808 : return static_cast<const SdrTextAniKindItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND)).GetValue();
1842 : }
1843 :
1844 133110 : SdrTextAniDirection SdrTextObj::GetTextAniDirection() const
1845 : {
1846 133110 : return static_cast<const SdrTextAniDirectionItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
1847 : }
1848 :
1849 : // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1850 : // painting rectangle. Rotation is excluded from the returned values.
1851 0 : GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1852 : Rectangle& rScrollRectangle, Rectangle& rPaintRectangle)
1853 : {
1854 0 : GDIMetaFile* pRetval = 0L;
1855 0 : SdrOutliner& rOutliner = ImpGetDrawOutliner();
1856 0 : Rectangle aTextRect;
1857 0 : Rectangle aAnchorRect;
1858 0 : Rectangle aPaintRect;
1859 0 : Fraction aFitXKorreg(1,1);
1860 0 : bool bContourFrame(IsContourTextFrame());
1861 :
1862 : // get outliner set up. To avoid getting a somehow rotated MetaFile,
1863 : // temporarily disable object rotation.
1864 0 : sal_Int32 nAngle(aGeo.nRotationAngle);
1865 0 : aGeo.nRotationAngle = 0L;
1866 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg );
1867 0 : aGeo.nRotationAngle = nAngle;
1868 :
1869 0 : Rectangle aScrollFrameRect(aPaintRect);
1870 0 : const SfxItemSet& rSet = GetObjectItemSet();
1871 0 : SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
1872 :
1873 0 : if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection)
1874 : {
1875 0 : aScrollFrameRect.Left() = aAnchorRect.Left();
1876 0 : aScrollFrameRect.Right() = aAnchorRect.Right();
1877 : }
1878 :
1879 0 : if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection)
1880 : {
1881 0 : aScrollFrameRect.Top() = aAnchorRect.Top();
1882 0 : aScrollFrameRect.Bottom() = aAnchorRect.Bottom();
1883 : }
1884 :
1885 : // create the MetaFile
1886 0 : pRetval = new GDIMetaFile;
1887 0 : ScopedVclPtrInstance< VirtualDevice > pBlackHole;
1888 0 : pBlackHole->EnableOutput(false);
1889 0 : pRetval->Record(pBlackHole);
1890 0 : Point aPaintPos = aPaintRect.TopLeft();
1891 :
1892 0 : rOutliner.Draw(pBlackHole, aPaintPos);
1893 :
1894 0 : pRetval->Stop();
1895 0 : pRetval->WindStart();
1896 :
1897 : // return PaintRectanglePixel and pRetval;
1898 0 : rScrollRectangle = aScrollFrameRect;
1899 0 : rPaintRectangle = aPaintRect;
1900 :
1901 0 : return pRetval;
1902 : }
1903 :
1904 : // Access to TextAnimationAllowed flag
1905 29201 : bool SdrTextObj::IsAutoFit() const
1906 : {
1907 29201 : return GetFitToSize()==SDRTEXTFIT_AUTOFIT;
1908 : }
1909 :
1910 227071 : bool SdrTextObj::IsFitToSize() const
1911 : {
1912 227071 : const SdrFitToSizeType eFit=GetFitToSize();
1913 227071 : return (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
1914 : }
1915 :
1916 18 : void SdrTextObj::SetTextAnimationAllowed(bool bNew)
1917 : {
1918 18 : if(mbTextAnimationAllowed != bNew)
1919 : {
1920 18 : mbTextAnimationAllowed = bNew;
1921 18 : ActionChanged();
1922 : }
1923 18 : }
1924 :
1925 : /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1926 4 : void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
1927 : {
1928 4 : const EditStatusFlags nStat = pEditStatus->GetStatusWord();
1929 4 : const bool bGrowX = bool(nStat & EditStatusFlags::TEXTWIDTHCHANGED);
1930 4 : const bool bGrowY = bool(nStat & EditStatusFlags::TEXTHEIGHTCHANGED);
1931 4 : if(bTextFrame && (bGrowX || bGrowY))
1932 : {
1933 4 : if ((bGrowX && IsAutoGrowWidth()) || (bGrowY && IsAutoGrowHeight()))
1934 : {
1935 2 : AdjustTextFrameWidthAndHeight();
1936 : }
1937 2 : else if (IsAutoFit() && !mbInDownScale)
1938 : {
1939 : assert(pEdtOutl);
1940 2 : mbInDownScale = true;
1941 :
1942 : // sucks that we cannot disable paints via
1943 : // pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
1944 : // formatting as well, then.
1945 2 : ImpAutoFitText(*pEdtOutl);
1946 2 : mbInDownScale = false;
1947 : }
1948 : }
1949 4 : }
1950 :
1951 : /** returns the currently active text. */
1952 659435 : SdrText* SdrTextObj::getActiveText() const
1953 : {
1954 659435 : if( !mpText )
1955 6184 : return getText( 0 );
1956 : else
1957 653251 : return mpText;
1958 : }
1959 :
1960 : /** returns the nth available text. */
1961 578355 : SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const
1962 : {
1963 578355 : if( nIndex == 0 )
1964 : {
1965 578355 : if( mpText == 0 )
1966 67840 : const_cast< SdrTextObj* >(this)->mpText = new SdrText( *(const_cast< SdrTextObj* >(this)) );
1967 578355 : return mpText;
1968 : }
1969 : else
1970 : {
1971 0 : return 0;
1972 : }
1973 : }
1974 :
1975 : /** returns the number of texts available for this object. */
1976 508370 : sal_Int32 SdrTextObj::getTextCount() const
1977 : {
1978 508370 : return 1;
1979 : }
1980 :
1981 : /** changes the current active text */
1982 2 : void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ )
1983 : {
1984 2 : }
1985 :
1986 : /** returns the index of the text that contains the given point or -1 */
1987 0 : sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const
1988 : {
1989 0 : return 0;
1990 : }
1991 :
1992 0 : void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
1993 : {
1994 0 : static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem);
1995 435 : }
1996 :
1997 :
1998 :
1999 : // The concept of the text object:
2000 : // ~~~~~~~~~~~~~~~~~~~~~~~~
2001 : // Attributes/Variations:
2002 : // - bool text frame / graphics object with caption
2003 : // - bool FontWork (if it is not a text frame and not a ContourTextFrame)
2004 : // - bool ContourTextFrame (if it is not a text frame and not Fontwork)
2005 : // - long rotation angle (if it is not FontWork)
2006 : // - long text frame margins (if it is not FontWork)
2007 : // - bool FitToSize (if it is not FontWork)
2008 : // - bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
2009 : // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
2010 : // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
2011 : // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
2012 : // - enum ticker text (if it is not FontWork)
2013 :
2014 : // Every derived object is either a text frame (bTextFrame=true)
2015 : // or a drawing object with a caption (bTextFrame=false).
2016 :
2017 : // Default anchoring for text frames:
2018 : // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
2019 : // = static Pool defaults
2020 : // Default anchoring for drawing objects with a caption:
2021 : // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
2022 : // via "hard" attribution of SdrAttrObj
2023 :
2024 : // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
2025 : // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
2026 : // left of the rectangle (aGeo.nRotationAngle)) which is the basis for anchoring
2027 : // text. We then subtract the text frame margins from this rectangle, as a re-
2028 : // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
2029 : // calculate the anchoring point and the painting area, depending on the hori-
2030 : // zontal and vertical adjustment of the text (SdrTextVertAdjust,
2031 : // SdrTextHorzAdjust).
2032 : // In the case of drawing objects with a caption the painting area might well
2033 : // be larger than the anchoring area, for text frames on the other hand, it is
2034 : // always of the same or a smaller size (except when there are negative text
2035 : // frame margins).
2036 :
2037 : // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2038 : // FitToSize is turned on, the painting area is always equal to the anchoring
2039 : // area. Additionally, FitToSize doesn't allow automatic line breaks.
2040 :
2041 : // ContourTextFrame:
2042 : // - long rotation angle
2043 : // - long text frame margins (maybe later)
2044 : // - bool FitToSize (maybe later)
2045 : // - bool AutoGrowingWidth/Height (maybe much later)
2046 : // - long Min/MaxFrameWidth/Height (maybe much later)
2047 : // - enum horizontal text anchoring (maybe later, for now: left, centered)
2048 : // - enum vertical text anchoring (maybe later, for now: top)
2049 : // - enum ticker text (maybe later, maybe even with correct clipping)
2050 :
2051 : // When making changes, check these:
2052 : // - Paint
2053 : // - HitTest
2054 : // - ConvertToPoly
2055 : // - Edit
2056 : // - Printing, Saving, Painting in neighboring View while editing
2057 : // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2058 : // - FillColorChanged while editin
2059 : // - and many more...
2060 :
2061 :
2062 :
2063 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|