1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 27 #include <svl/style.hxx> 28 #include <svx/svdotext.hxx> 29 #include "svx/svditext.hxx" 30 #include <svx/svdmodel.hxx> // fuer GetMaxObjSize und GetStyleSheetPool 31 #include <svx/svdoutl.hxx> 32 #include <svx/svdorect.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight 33 #include <svx/svdocapt.hxx> // fuer SetDirty bei NbcAdjustTextFrameWidthAndHeight 34 #include <svx/svdetc.hxx> 35 #include <editeng/writingmodeitem.hxx> 36 #include <editeng/editeng.hxx> 37 #include <editeng/eeitem.hxx> 38 #include <editeng/flditem.hxx> 39 #include <svx/sdtfchim.hxx> 40 41 42 #include <editeng/editview.hxx> 43 #include <svl/smplhint.hxx> 44 #include <svl/whiter.hxx> 45 #include <editeng/outlobj.hxx> 46 #include <editeng/outliner.hxx> 47 #include <editeng/eeitem.hxx> 48 #include <editeng/editobj.hxx> 49 #include <editeng/fhgtitem.hxx> 50 51 #include <editeng/charscaleitem.hxx> 52 #include <svl/style.hxx> 53 #include <svl/itemiter.hxx> 54 #include <editeng/lrspitem.hxx> 55 #include <svl/itempool.hxx> 56 #include <editeng/numitem.hxx> 57 #include <editeng/editeng.hxx> 58 #include <editeng/postitem.hxx> 59 60 //////////////////////////////////////////////////////////////////////////////////////////////////// 61 // 62 // @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ 63 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ 64 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ 65 // @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ 66 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ 67 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ 68 // @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ 69 // 70 // Attribute, StyleSheets und AutoGrow 71 // 72 //////////////////////////////////////////////////////////////////////////////////////////////////// 73 74 FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt, FASTBOOL bWdt) const 75 { 76 if (bTextFrame && pModel!=NULL && !rR.IsEmpty()) 77 { 78 SdrFitToSizeType eFit=GetFitToSize(); 79 FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); 80 FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth(); 81 FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight(); 82 SdrTextAniKind eAniKind=GetTextAniKind(); 83 SdrTextAniDirection eAniDir=GetTextAniDirection(); 84 FASTBOOL bScroll=eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE; 85 FASTBOOL bHScroll=bScroll && (eAniDir==SDRTEXTANI_LEFT || eAniDir==SDRTEXTANI_RIGHT); 86 FASTBOOL bVScroll=bScroll && (eAniDir==SDRTEXTANI_UP || eAniDir==SDRTEXTANI_DOWN); 87 if (!bFitToSize && (bWdtGrow || bHgtGrow)) 88 { 89 Rectangle aR0(rR); 90 long nHgt=0,nMinHgt=0,nMaxHgt=0; 91 long nWdt=0,nMinWdt=0,nMaxWdt=0; 92 Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--; 93 Size aMaxSiz(100000,100000); 94 Size aTmpSiz(pModel->GetMaxObjSize()); 95 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); 96 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); 97 if (bWdtGrow) 98 { 99 nMinWdt=GetMinTextFrameWidth(); 100 nMaxWdt=GetMaxTextFrameWidth(); 101 if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); 102 if (nMinWdt<=0) nMinWdt=1; 103 aSiz.Width()=nMaxWdt; 104 } 105 if (bHgtGrow) 106 { 107 nMinHgt=GetMinTextFrameHeight(); 108 nMaxHgt=GetMaxTextFrameHeight(); 109 if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); 110 if (nMinHgt<=0) nMinHgt=1; 111 aSiz.Height()=nMaxHgt; 112 } 113 long nHDist=GetTextLeftDistance()+GetTextRightDistance(); 114 long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); 115 aSiz.Width()-=nHDist; 116 aSiz.Height()-=nVDist; 117 if (aSiz.Width()<2) aSiz.Width()=2; // Mindestgroesse 2 118 if (aSiz.Height()<2) aSiz.Height()=2; // Mindestgroesse 2 119 120 // #101684# 121 sal_Bool bInEditMode = IsInEditMode(); 122 123 if(!bInEditMode) 124 { 125 if (bHScroll) aSiz.Width()=0x0FFFFFFF; // Laufschrift nicht umbrechen 126 if (bVScroll) aSiz.Height()=0x0FFFFFFF; 127 } 128 129 if(pEdtOutl) 130 { 131 pEdtOutl->SetMaxAutoPaperSize(aSiz); 132 if (bWdtGrow) { 133 Size aSiz2(pEdtOutl->CalcTextSize()); 134 nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz 135 if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz 136 } else { 137 nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz 138 } 139 } else { 140 Outliner& rOutliner=ImpGetDrawOutliner(); 141 rOutliner.SetPaperSize(aSiz); 142 rOutliner.SetUpdateMode(sal_True); 143 // !!! hier sollte ich wohl auch noch mal die Optimierung mit 144 // bPortionInfoChecked usw einbauen 145 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 146 if ( pOutlinerParaObject != NULL ) 147 { 148 rOutliner.SetText(*pOutlinerParaObject); 149 rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); 150 } 151 if (bWdtGrow) 152 { 153 Size aSiz2(rOutliner.CalcTextSize()); 154 nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz 155 if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz 156 } else { 157 nHgt=rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz 158 } 159 rOutliner.Clear(); 160 } 161 if (nWdt<nMinWdt) nWdt=nMinWdt; 162 if (nWdt>nMaxWdt) nWdt=nMaxWdt; 163 nWdt+=nHDist; 164 if (nWdt<1) nWdt=1; // nHDist kann auch negativ sein 165 if (nHgt<nMinHgt) nHgt=nMinHgt; 166 if (nHgt>nMaxHgt) nHgt=nMaxHgt; 167 nHgt+=nVDist; 168 if (nHgt<1) nHgt=1; // nVDist kann auch negativ sein 169 long nWdtGrow=nWdt-(rR.Right()-rR.Left()); 170 long nHgtGrow=nHgt-(rR.Bottom()-rR.Top()); 171 if (nWdtGrow==0) bWdtGrow=sal_False; 172 if (nHgtGrow==0) bHgtGrow=sal_False; 173 if (bWdtGrow || bHgtGrow) { 174 if (bWdtGrow) { 175 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); 176 if (eHAdj==SDRTEXTHORZADJUST_LEFT) rR.Right()+=nWdtGrow; 177 else if (eHAdj==SDRTEXTHORZADJUST_RIGHT) rR.Left()-=nWdtGrow; 178 else { 179 long nWdtGrow2=nWdtGrow/2; 180 rR.Left()-=nWdtGrow2; 181 rR.Right()=rR.Left()+nWdt; 182 } 183 } 184 if (bHgtGrow) { 185 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); 186 if (eVAdj==SDRTEXTVERTADJUST_TOP) rR.Bottom()+=nHgtGrow; 187 else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) rR.Top()-=nHgtGrow; 188 else { 189 long nHgtGrow2=nHgtGrow/2; 190 rR.Top()-=nHgtGrow2; 191 rR.Bottom()=rR.Top()+nHgt; 192 } 193 } 194 if (aGeo.nDrehWink!=0) { 195 Point aD1(rR.TopLeft()); 196 aD1-=aR0.TopLeft(); 197 Point aD2(aD1); 198 RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos); 199 aD2-=aD1; 200 rR.Move(aD2.X(),aD2.Y()); 201 } 202 return sal_True; 203 } 204 } 205 } 206 return sal_False; 207 } 208 209 FASTBOOL SdrTextObj::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) 210 { 211 FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aRect,bHgt,bWdt); 212 if (bRet) { 213 SetRectsDirty(); 214 if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack 215 ((SdrRectObj*)this)->SetXPolyDirty(); 216 } 217 if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack 218 ((SdrCaptionObj*)this)->ImpRecalcTail(); 219 } 220 } 221 return bRet; 222 } 223 224 FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) 225 { 226 Rectangle aNeuRect(aRect); 227 FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt); 228 if (bRet) { 229 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); 230 // #110094#-14 SendRepaintBroadcast(); 231 aRect=aNeuRect; 232 SetRectsDirty(); 233 if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack 234 ((SdrRectObj*)this)->SetXPolyDirty(); 235 } 236 if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack 237 ((SdrCaptionObj*)this)->ImpRecalcTail(); 238 } 239 SetChanged(); 240 BroadcastObjectChange(); 241 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); 242 } 243 return bRet; 244 } 245 246 void SdrTextObj::ImpSetTextStyleSheetListeners() 247 { 248 SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL; 249 if (pStylePool!=NULL) 250 { 251 Container aStyles(1024,64,64); 252 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 253 if (pOutlinerParaObject!=NULL) 254 { 255 // Zunaechst werden alle im ParaObject enthaltenen StyleSheets 256 // im Container aStyles gesammelt. Dazu wird die Family jeweils 257 // ans Ende des StyleSheet-Namen drangehaengt. 258 const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject(); 259 XubString aStyleName; 260 SfxStyleFamily eStyleFam; 261 sal_uInt16 nParaAnz=rTextObj.GetParagraphCount(); 262 263 for(sal_uInt16 nParaNum(0); nParaNum < nParaAnz; nParaNum++) 264 { 265 rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam); 266 267 if(aStyleName.Len()) 268 { 269 XubString aFam = UniString::CreateFromInt32((sal_uInt16)eStyleFam); 270 aFam.Expand(5); 271 272 aStyleName += sal_Unicode('|'); 273 aStyleName += aFam; 274 275 sal_Bool bFnd(sal_False); 276 sal_uInt32 nNum(aStyles.Count()); 277 278 while(!bFnd && nNum > 0) 279 { 280 // kein StyleSheet doppelt! 281 nNum--; 282 bFnd = (aStyleName.Equals(*(XubString*)aStyles.GetObject(nNum))); 283 } 284 285 if(!bFnd) 286 { 287 aStyles.Insert(new XubString(aStyleName), CONTAINER_APPEND); 288 } 289 } 290 } 291 } 292 293 // nun die Strings im Container durch StyleSheet* ersetzten 294 sal_uIntPtr nNum=aStyles.Count(); 295 while (nNum>0) { 296 nNum--; 297 XubString* pName=(XubString*)aStyles.GetObject(nNum); 298 299 // UNICODE: String aFam(pName->Cut(pName->Len()-6)); 300 String aFam = pName->Copy(0, pName->Len() - 6); 301 302 aFam.Erase(0,1); 303 aFam.EraseTrailingChars(); 304 305 // UNICODE: sal_uInt16 nFam=sal_uInt16(aFam); 306 sal_uInt16 nFam = (sal_uInt16)aFam.ToInt32(); 307 308 SfxStyleFamily eFam=(SfxStyleFamily)nFam; 309 SfxStyleSheetBase* pStyleBase=pStylePool->Find(*pName,eFam); 310 SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pStyleBase); 311 delete pName; 312 if (pStyle!=NULL && pStyle!=GetStyleSheet()) { 313 aStyles.Replace(pStyle,nNum); 314 } else { 315 aStyles.Remove(nNum); 316 } 317 } 318 // jetzt alle ueberfluessigen StyleSheets entfernen 319 nNum=GetBroadcasterCount(); 320 while (nNum>0) { 321 nNum--; 322 SfxBroadcaster* pBroadcast=GetBroadcasterJOE((sal_uInt16)nNum); 323 SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast); 324 if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // Sonderbehandlung fuer den StyleSheet des Objekts 325 if (aStyles.GetPos(pStyle)==CONTAINER_ENTRY_NOTFOUND) { 326 EndListening(*pStyle); 327 } 328 } 329 } 330 // und schliesslich alle in aStyles enthaltenen StyleSheets mit den vorhandenen Broadcastern mergen 331 nNum=aStyles.Count(); 332 while (nNum>0) { 333 nNum--; 334 SfxStyleSheet* pStyle=(SfxStyleSheet*)aStyles.GetObject(nNum); 335 // StartListening soll selbst nachsehen, ob hier nicht evtl. schon gehorcht wird 336 StartListening(*pStyle,sal_True); 337 } 338 } 339 } 340 341 void SdrTextObj::NbcResizeTextAttributes(const Fraction& xFact, const Fraction& yFact) 342 { 343 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 344 if (pOutlinerParaObject!=NULL && xFact.IsValid() && yFact.IsValid()) 345 { 346 Fraction n100(100,1); 347 long nX=long(xFact*n100); 348 long nY=long(yFact*n100); 349 if (nX<0) nX=-nX; 350 if (nX<1) nX=1; 351 if (nX>0xFFFF) nX=0xFFFF; 352 if (nY<0) nY=-nY; 353 if (nY<1) nY=1; 354 if (nY>0xFFFF) nY=0xFFFF; 355 if (nX!=100 || nY!=100) 356 { 357 // Rahmenattribute 358 const SfxItemSet& rSet = GetObjectItemSet(); 359 const SvxCharScaleWidthItem& rOldWdt=(SvxCharScaleWidthItem&)rSet.Get(EE_CHAR_FONTWIDTH); 360 const SvxFontHeightItem& rOldHgt=(SvxFontHeightItem&)rSet.Get(EE_CHAR_FONTHEIGHT); 361 362 // erstmal die alten Werte holen 363 long nRelWdt=rOldWdt.GetValue(); 364 long nAbsHgt=rOldHgt.GetHeight(); 365 long nRelHgt=rOldHgt.GetProp(); 366 367 // Relative Breite aendern 368 nRelWdt*=nX; 369 nRelWdt/=nY; 370 if (nRelWdt<0) nRelWdt=-nRelWdt; // nicht negativ 371 if (nRelWdt<=0) nRelWdt=1; // und mind. 1% 372 if (nRelWdt>0xFFFF) nRelWdt=0xFFFF; 373 374 // Absolute Hoehe aendern 375 nAbsHgt*=nY; 376 nAbsHgt/=100; 377 if (nAbsHgt<0) nAbsHgt=-nAbsHgt; // nicht negativ 378 if (nAbsHgt<=0) nAbsHgt=1; // und mind. 1 379 if (nAbsHgt>0xFFFF) nAbsHgt=0xFFFF; 380 381 // und nun attributieren 382 SetObjectItem(SvxCharScaleWidthItem( (sal_uInt16) nRelWdt, EE_CHAR_FONTWIDTH)); 383 SetObjectItem(SvxFontHeightItem(nAbsHgt,(sal_uInt16)nRelHgt, EE_CHAR_FONTHEIGHT)); 384 // Zeichen- und Absatzattribute innerhalb des OutlinerParaObjects 385 Outliner& rOutliner=ImpGetDrawOutliner(); 386 rOutliner.SetPaperSize(Size(LONG_MAX,LONG_MAX)); 387 rOutliner.SetText(*pOutlinerParaObject); 388 rOutliner.DoStretchChars((sal_uInt16)nX,(sal_uInt16)nY); 389 OutlinerParaObject* pNewPara=rOutliner.CreateParaObject(); 390 NbcSetOutlinerParaObject(pNewPara); 391 rOutliner.Clear(); 392 } 393 } 394 } 395 396 /** #103836# iterates over the paragraphs of a given SdrObject and removes all 397 hard set character attributes with the which ids contained in the 398 given vector 399 */ 400 void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds ) 401 { 402 sal_Int32 nText = getTextCount(); 403 404 while( --nText >= 0 ) 405 { 406 SdrText* pText = getText( nText ); 407 OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0; 408 409 if(pOutlinerParaObject) 410 { 411 Outliner* pOutliner = 0; 412 413 if( pEdtOutl || (pText == getActiveText()) ) 414 pOutliner = pEdtOutl; 415 416 if(!pOutliner) 417 { 418 pOutliner = &ImpGetDrawOutliner(); 419 pOutliner->SetText(*pOutlinerParaObject); 420 } 421 422 ESelection aSelAll( 0, 0, 0xffff, 0xffff ); 423 std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() ); 424 while( aIter != rCharWhichIds.end() ) 425 { 426 pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) ); 427 } 428 429 if(!pEdtOutl || (pText != getActiveText()) ) 430 { 431 const sal_uInt32 nParaCount = pOutliner->GetParagraphCount(); 432 OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, (sal_uInt16)nParaCount); 433 pOutliner->Clear(); 434 NbcSetOutlinerParaObjectForText(pTemp, pText); 435 } 436 } 437 } 438 } 439 440 bool SdrTextObj::HasText() const 441 { 442 if( pEdtOutl ) 443 return HasEditText(); 444 445 OutlinerParaObject* pOPO = GetOutlinerParaObject(); 446 447 bool bHasText = false; 448 if( pOPO ) 449 { 450 const EditTextObject& rETO = pOPO->GetTextObject(); 451 sal_uInt16 nParaCount = rETO.GetParagraphCount(); 452 453 if( nParaCount > 0 ) 454 bHasText = (nParaCount > 1) || (rETO.GetText( 0 ).Len() != 0); 455 } 456 457 return bHasText; 458 } 459