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