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 FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth(); 79 FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight(); 80 SdrTextAniKind eAniKind=GetTextAniKind(); 81 SdrTextAniDirection eAniDir=GetTextAniDirection(); 82 FASTBOOL bScroll=eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE; 83 FASTBOOL bHScroll=bScroll && (eAniDir==SDRTEXTANI_LEFT || eAniDir==SDRTEXTANI_RIGHT); 84 FASTBOOL bVScroll=bScroll && (eAniDir==SDRTEXTANI_UP || eAniDir==SDRTEXTANI_DOWN); 85 if (!GetFitToSize() && (bWdtGrow || bHgtGrow)) 86 { 87 Rectangle aR0(rR); 88 long nHgt=0,nMinHgt=0,nMaxHgt=0; 89 long nWdt=0,nMinWdt=0,nMaxWdt=0; 90 Size aSiz(rR.GetSize()); aSiz.Width()--; aSiz.Height()--; 91 Size aMaxSiz(100000,100000); 92 Size aTmpSiz(pModel->GetMaxObjSize()); 93 if (aTmpSiz.Width()!=0) aMaxSiz.Width()=aTmpSiz.Width(); 94 if (aTmpSiz.Height()!=0) aMaxSiz.Height()=aTmpSiz.Height(); 95 if (bWdtGrow) 96 { 97 nMinWdt=GetMinTextFrameWidth(); 98 nMaxWdt=GetMaxTextFrameWidth(); 99 if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); 100 if (nMinWdt<=0) nMinWdt=1; 101 aSiz.Width()=nMaxWdt; 102 } 103 if (bHgtGrow) 104 { 105 nMinHgt=GetMinTextFrameHeight(); 106 nMaxHgt=GetMaxTextFrameHeight(); 107 if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); 108 if (nMinHgt<=0) nMinHgt=1; 109 aSiz.Height()=nMaxHgt; 110 } 111 long nHDist=GetTextLeftDistance()+GetTextRightDistance(); 112 long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); 113 aSiz.Width()-=nHDist; 114 aSiz.Height()-=nVDist; 115 if (aSiz.Width()<2) aSiz.Width()=2; // Mindestgroesse 2 116 if (aSiz.Height()<2) aSiz.Height()=2; // Mindestgroesse 2 117 118 // #101684# 119 sal_Bool bInEditMode = IsInEditMode(); 120 121 if(!bInEditMode) 122 { 123 if (bHScroll) aSiz.Width()=0x0FFFFFFF; // Laufschrift nicht umbrechen 124 if (bVScroll) aSiz.Height()=0x0FFFFFFF; 125 } 126 127 if(pEdtOutl) 128 { 129 pEdtOutl->SetMaxAutoPaperSize(aSiz); 130 if (bWdtGrow) { 131 Size aSiz2(pEdtOutl->CalcTextSize()); 132 nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz 133 if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz 134 } else { 135 nHgt=pEdtOutl->GetTextHeight()+1; // lieber etwas Tolleranz 136 } 137 } else { 138 Outliner& rOutliner=ImpGetDrawOutliner(); 139 rOutliner.SetPaperSize(aSiz); 140 rOutliner.SetUpdateMode(sal_True); 141 // !!! hier sollte ich wohl auch noch mal die Optimierung mit 142 // bPortionInfoChecked usw einbauen 143 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 144 if ( pOutlinerParaObject != NULL ) 145 { 146 rOutliner.SetText(*pOutlinerParaObject); 147 rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); 148 } 149 if (bWdtGrow) 150 { 151 Size aSiz2(rOutliner.CalcTextSize()); 152 nWdt=aSiz2.Width()+1; // lieber etwas Tolleranz 153 if (bHgtGrow) nHgt=aSiz2.Height()+1; // lieber etwas Tolleranz 154 } else { 155 nHgt=rOutliner.GetTextHeight()+1; // lieber etwas Tolleranz 156 } 157 rOutliner.Clear(); 158 } 159 if (nWdt<nMinWdt) nWdt=nMinWdt; 160 if (nWdt>nMaxWdt) nWdt=nMaxWdt; 161 nWdt+=nHDist; 162 if (nWdt<1) nWdt=1; // nHDist kann auch negativ sein 163 if (nHgt<nMinHgt) nHgt=nMinHgt; 164 if (nHgt>nMaxHgt) nHgt=nMaxHgt; 165 nHgt+=nVDist; 166 if (nHgt<1) nHgt=1; // nVDist kann auch negativ sein 167 long nWdtGrow=nWdt-(rR.Right()-rR.Left()); 168 long nHgtGrow=nHgt-(rR.Bottom()-rR.Top()); 169 if (nWdtGrow==0) bWdtGrow=sal_False; 170 if (nHgtGrow==0) bHgtGrow=sal_False; 171 if (bWdtGrow || bHgtGrow) { 172 if (bWdtGrow) { 173 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); 174 if (eHAdj==SDRTEXTHORZADJUST_LEFT) rR.Right()+=nWdtGrow; 175 else if (eHAdj==SDRTEXTHORZADJUST_RIGHT) rR.Left()-=nWdtGrow; 176 else { 177 long nWdtGrow2=nWdtGrow/2; 178 rR.Left()-=nWdtGrow2; 179 rR.Right()=rR.Left()+nWdt; 180 } 181 } 182 if (bHgtGrow) { 183 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); 184 if (eVAdj==SDRTEXTVERTADJUST_TOP) rR.Bottom()+=nHgtGrow; 185 else if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) rR.Top()-=nHgtGrow; 186 else { 187 long nHgtGrow2=nHgtGrow/2; 188 rR.Top()-=nHgtGrow2; 189 rR.Bottom()=rR.Top()+nHgt; 190 } 191 } 192 if (aGeo.nDrehWink!=0) { 193 Point aD1(rR.TopLeft()); 194 aD1-=aR0.TopLeft(); 195 Point aD2(aD1); 196 RotatePoint(aD2,Point(),aGeo.nSin,aGeo.nCos); 197 aD2-=aD1; 198 rR.Move(aD2.X(),aD2.Y()); 199 } 200 return sal_True; 201 } 202 } 203 } 204 return sal_False; 205 } 206 207 FASTBOOL SdrTextObj::NbcAdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) 208 { 209 FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aRect,bHgt,bWdt); 210 if (bRet) { 211 SetRectsDirty(); 212 if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack 213 ((SdrRectObj*)this)->SetXPolyDirty(); 214 } 215 if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack 216 ((SdrCaptionObj*)this)->ImpRecalcTail(); 217 } 218 } 219 return bRet; 220 } 221 222 FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(FASTBOOL bHgt, FASTBOOL bWdt) 223 { 224 Rectangle aNeuRect(aRect); 225 FASTBOOL bRet=AdjustTextFrameWidthAndHeight(aNeuRect,bHgt,bWdt); 226 if (bRet) { 227 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); 228 // #110094#-14 SendRepaintBroadcast(); 229 aRect=aNeuRect; 230 SetRectsDirty(); 231 if (HAS_BASE(SdrRectObj,this)) { // mal wieder 'nen Hack 232 ((SdrRectObj*)this)->SetXPolyDirty(); 233 } 234 if (HAS_BASE(SdrCaptionObj,this)) { // mal wieder 'nen Hack 235 ((SdrCaptionObj*)this)->ImpRecalcTail(); 236 } 237 SetChanged(); 238 BroadcastObjectChange(); 239 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); 240 } 241 return bRet; 242 } 243 244 void SdrTextObj::ImpSetTextStyleSheetListeners() 245 { 246 SfxStyleSheetBasePool* pStylePool=pModel!=NULL ? pModel->GetStyleSheetPool() : NULL; 247 if (pStylePool!=NULL) 248 { 249 Container aStyles(1024,64,64); 250 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 251 if (pOutlinerParaObject!=NULL) 252 { 253 // Zunaechst werden alle im ParaObject enthaltenen StyleSheets 254 // im Container aStyles gesammelt. Dazu wird die Family jeweils 255 // ans Ende des StyleSheet-Namen drangehaengt. 256 const EditTextObject& rTextObj=pOutlinerParaObject->GetTextObject(); 257 XubString aStyleName; 258 SfxStyleFamily eStyleFam; 259 sal_uInt16 nParaAnz=rTextObj.GetParagraphCount(); 260 261 for(sal_uInt16 nParaNum(0); nParaNum < nParaAnz; nParaNum++) 262 { 263 rTextObj.GetStyleSheet(nParaNum, aStyleName, eStyleFam); 264 265 if(aStyleName.Len()) 266 { 267 XubString aFam = UniString::CreateFromInt32((sal_uInt16)eStyleFam); 268 aFam.Expand(5); 269 270 aStyleName += sal_Unicode('|'); 271 aStyleName += aFam; 272 273 sal_Bool bFnd(sal_False); 274 sal_uInt32 nNum(aStyles.Count()); 275 276 while(!bFnd && nNum > 0) 277 { 278 // kein StyleSheet doppelt! 279 nNum--; 280 bFnd = (aStyleName.Equals(*(XubString*)aStyles.GetObject(nNum))); 281 } 282 283 if(!bFnd) 284 { 285 aStyles.Insert(new XubString(aStyleName), CONTAINER_APPEND); 286 } 287 } 288 } 289 } 290 291 // nun die Strings im Container durch StyleSheet* ersetzten 292 sal_uIntPtr nNum=aStyles.Count(); 293 while (nNum>0) { 294 nNum--; 295 XubString* pName=(XubString*)aStyles.GetObject(nNum); 296 297 // UNICODE: String aFam(pName->Cut(pName->Len()-6)); 298 String aFam = pName->Copy(0, pName->Len() - 6); 299 300 aFam.Erase(0,1); 301 aFam.EraseTrailingChars(); 302 303 // UNICODE: sal_uInt16 nFam=sal_uInt16(aFam); 304 sal_uInt16 nFam = (sal_uInt16)aFam.ToInt32(); 305 306 SfxStyleFamily eFam=(SfxStyleFamily)nFam; 307 SfxStyleSheetBase* pStyleBase=pStylePool->Find(*pName,eFam); 308 SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pStyleBase); 309 delete pName; 310 if (pStyle!=NULL && pStyle!=GetStyleSheet()) { 311 aStyles.Replace(pStyle,nNum); 312 } else { 313 aStyles.Remove(nNum); 314 } 315 } 316 // jetzt alle ueberfluessigen StyleSheets entfernen 317 nNum=GetBroadcasterCount(); 318 while (nNum>0) { 319 nNum--; 320 SfxBroadcaster* pBroadcast=GetBroadcasterJOE((sal_uInt16)nNum); 321 SfxStyleSheet* pStyle=PTR_CAST(SfxStyleSheet,pBroadcast); 322 if (pStyle!=NULL && pStyle!=GetStyleSheet()) { // Sonderbehandlung fuer den StyleSheet des Objekts 323 if (aStyles.GetPos(pStyle)==CONTAINER_ENTRY_NOTFOUND) { 324 EndListening(*pStyle); 325 } 326 } 327 } 328 // und schliesslich alle in aStyles enthaltenen StyleSheets mit den vorhandenen Broadcastern mergen 329 nNum=aStyles.Count(); 330 while (nNum>0) { 331 nNum--; 332 SfxStyleSheet* pStyle=(SfxStyleSheet*)aStyles.GetObject(nNum); 333 // StartListening soll selbst nachsehen, ob hier nicht evtl. schon gehorcht wird 334 StartListening(*pStyle,sal_True); 335 } 336 } 337 } 338 339 void SdrTextObj::NbcResizeTextAttributes(const Fraction& xFact, const Fraction& yFact) 340 { 341 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); 342 if (pOutlinerParaObject!=NULL && xFact.IsValid() && yFact.IsValid()) 343 { 344 Fraction n100(100,1); 345 long nX=long(xFact*n100); 346 long nY=long(yFact*n100); 347 if (nX<0) nX=-nX; 348 if (nX<1) nX=1; 349 if (nX>0xFFFF) nX=0xFFFF; 350 if (nY<0) nY=-nY; 351 if (nY<1) nY=1; 352 if (nY>0xFFFF) nY=0xFFFF; 353 if (nX!=100 || nY!=100) 354 { 355 // Rahmenattribute 356 const SfxItemSet& rSet = GetObjectItemSet(); 357 const SvxCharScaleWidthItem& rOldWdt=(SvxCharScaleWidthItem&)rSet.Get(EE_CHAR_FONTWIDTH); 358 const SvxFontHeightItem& rOldHgt=(SvxFontHeightItem&)rSet.Get(EE_CHAR_FONTHEIGHT); 359 360 // erstmal die alten Werte holen 361 long nRelWdt=rOldWdt.GetValue(); 362 long nAbsHgt=rOldHgt.GetHeight(); 363 long nRelHgt=rOldHgt.GetProp(); 364 365 // Relative Breite aendern 366 nRelWdt*=nX; 367 nRelWdt/=nY; 368 if (nRelWdt<0) nRelWdt=-nRelWdt; // nicht negativ 369 if (nRelWdt<=0) nRelWdt=1; // und mind. 1% 370 if (nRelWdt>0xFFFF) nRelWdt=0xFFFF; 371 372 // Absolute Hoehe aendern 373 nAbsHgt*=nY; 374 nAbsHgt/=100; 375 if (nAbsHgt<0) nAbsHgt=-nAbsHgt; // nicht negativ 376 if (nAbsHgt<=0) nAbsHgt=1; // und mind. 1 377 if (nAbsHgt>0xFFFF) nAbsHgt=0xFFFF; 378 379 // und nun attributieren 380 SetObjectItem(SvxCharScaleWidthItem( (sal_uInt16) nRelWdt, EE_CHAR_FONTWIDTH)); 381 SetObjectItem(SvxFontHeightItem(nAbsHgt,(sal_uInt16)nRelHgt, EE_CHAR_FONTHEIGHT)); 382 // Zeichen- und Absatzattribute innerhalb des OutlinerParaObjects 383 Outliner& rOutliner=ImpGetDrawOutliner(); 384 rOutliner.SetPaperSize(Size(LONG_MAX,LONG_MAX)); 385 rOutliner.SetText(*pOutlinerParaObject); 386 rOutliner.DoStretchChars((sal_uInt16)nX,(sal_uInt16)nY); 387 OutlinerParaObject* pNewPara=rOutliner.CreateParaObject(); 388 NbcSetOutlinerParaObject(pNewPara); 389 rOutliner.Clear(); 390 } 391 } 392 } 393 394 /** #103836# iterates over the paragraphs of a given SdrObject and removes all 395 hard set character attributes with the which ids contained in the 396 given vector 397 */ 398 void SdrTextObj::RemoveOutlinerCharacterAttribs( const std::vector<sal_uInt16>& rCharWhichIds ) 399 { 400 sal_Int32 nText = getTextCount(); 401 402 while( --nText >= 0 ) 403 { 404 SdrText* pText = getText( nText ); 405 OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0; 406 407 if(pOutlinerParaObject) 408 { 409 Outliner* pOutliner = 0; 410 411 if( pEdtOutl || (pText == getActiveText()) ) 412 pOutliner = pEdtOutl; 413 414 if(!pOutliner) 415 { 416 pOutliner = &ImpGetDrawOutliner(); 417 pOutliner->SetText(*pOutlinerParaObject); 418 } 419 420 ESelection aSelAll( 0, 0, 0xffff, 0xffff ); 421 std::vector<sal_uInt16>::const_iterator aIter( rCharWhichIds.begin() ); 422 while( aIter != rCharWhichIds.end() ) 423 { 424 pOutliner->RemoveAttribs( aSelAll, false, (*aIter++) ); 425 } 426 427 if(!pEdtOutl || (pText != getActiveText()) ) 428 { 429 const sal_uInt32 nParaCount = pOutliner->GetParagraphCount(); 430 OutlinerParaObject* pTemp = pOutliner->CreateParaObject(0, (sal_uInt16)nParaCount); 431 pOutliner->Clear(); 432 NbcSetOutlinerParaObjectForText(pTemp, pText); 433 } 434 } 435 } 436 } 437 438 bool SdrTextObj::HasText() const 439 { 440 if( pEdtOutl ) 441 return HasEditText(); 442 443 OutlinerParaObject* pOPO = GetOutlinerParaObject(); 444 445 bool bHasText = false; 446 if( pOPO ) 447 { 448 const EditTextObject& rETO = pOPO->GetTextObject(); 449 sal_uInt16 nParaCount = rETO.GetParagraphCount(); 450 451 if( nParaCount > 0 ) 452 bHasText = (nParaCount > 1) || (rETO.GetText( 0 ).Len() != 0); 453 } 454 455 return bHasText; 456 } 457