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