/************************************************************************* * * $RCSfile: svdoattr.cxx,v $ * * $Revision: 1.36 $ * * last change: $Author: cl $ $Date: 2002-04-25 09:58:13 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #include "svdoattr.hxx" #include "xpool.hxx" #include "svditext.hxx" #include "svdtouch.hxx" #include "svdio.hxx" #include "svdmodel.hxx" #include "svdxout.hxx" #include "svdpage.hxx" #include "svdattr.hxx" #include "svdattrx.hxx" #include "svdpool.hxx" #include "svdotext.hxx" #include "svdocapt.hxx" #include "svdograf.hxx" #include "svdoole2.hxx" #include "svdorect.hxx" #include "svdocirc.hxx" #include "svdomeas.hxx" #ifndef _SFXSMPLHINT_HXX //autogen #include #endif #ifndef _SFXITEMITER_HXX //autogen #include #endif #ifndef _XENUM_HXX //autogen #include "xenum.hxx" #endif #ifndef _SVX_XLINEIT0_HXX //autogen #include "xlineit0.hxx" #endif #ifndef _SVX_XLNSTWIT_HXX //autogen #include "xlnstwit.hxx" #endif #ifndef _SVX_XLNEDWIT_HXX //autogen #include "xlnedwit.hxx" #endif #ifndef SVX_XFILLIT0_HXX //autogen #include "xfillit0.hxx" #endif #ifndef _SVX_XFLBMTIT_HXX //autogen #include "xflbmtit.hxx" #endif #ifndef _SVX_TEXTIT0_HXX //autogen #include "xtextit0.hxx" #endif #ifndef _SVX_XFLBSTIT_HXX //autogen #include "xflbstit.hxx" #endif #ifndef _SVX_XFLBTOXY_HXX //autogen #include "xflbtoxy.hxx" #endif #ifndef _SVX_XFTSHIT_HXX //autogen #include "xftshit.hxx" #endif #ifndef _EEITEMID_HXX #include #endif #ifndef _SVX_COLRITEM_HXX //autogen #include "colritem.hxx" #endif #ifndef _SVX_FONTITEM_HXX //autogen #include "fontitem.hxx" #endif #ifndef _SVX_FHGTITEM_HXX //autogen #include "fhgtitem.hxx" #endif //#include #ifndef _SVX_XLNSTCIT_HXX //autogen #include #endif #ifndef _SVX_XLNWTIT_HXX //autogen #include #endif #ifndef _SFXSTYLE_HXX //autogen #include #endif #ifndef _SFXSTYLE_HXX //autogen #include #endif #ifndef _SFX_WHITER_HXX //autogen #include #endif #ifndef _SVX_XLNCLIT_HXX //autogen #include #endif #ifndef _SVX_XFLCLIT_HXX //autogen #include #endif #ifndef _SVX_XLNTRIT_HXX //autogen #include #endif #ifndef _SVX_XFLTRIT_HXX //autogen #include #endif #ifndef _SVX_XFLHTIT_HXX //autogen #include #endif #ifndef _SVX_XLNEDIT_HXX //autogen #include #endif #ifndef _SVX_XLNEDCIT_HXX //autogen #include #endif #ifndef _SVX_XLNSTIT_HXX //autogen #include #endif #ifndef _SVX_ADJITEM_HXX #include #endif #ifndef _SVX_XFLBCKIT_HXX #include "xflbckit.hxx" #endif #ifndef _SVX_XBTMPIT_HXX #include "xbtmpit.hxx" #endif #ifndef _XTABLE_HXX #include "xtable.hxx" #endif #ifndef _SVX_XLNDSIT_HXX #include "xlndsit.hxx" #endif #ifndef _SVX_XFLGRIT_HXX #include "xflgrit.hxx" #endif #ifndef _SVX_XFLFTRIT_HXX #include "xflftrit.hxx" #endif //////////////////////////////////////////////////////////////////////////////////////////////////// TYPEINIT1(SdrAttrObj,SdrObject); SdrAttrObj::SdrAttrObj() : mpStyleSheet(NULL), mpObjectItemSet(NULL) { } SdrAttrObj::~SdrAttrObj() { ImpDeleteItemSet(); } void SdrAttrObj::ImpDeleteItemSet() { if(mpObjectItemSet) { if(GetStyleSheet()) RemoveStyleSheet(); delete mpObjectItemSet; mpObjectItemSet = 0L; } } void SdrAttrObj::ImpForceItemSet() { if(!mpObjectItemSet) { SfxItemPool* pPool = GetItemPool(); mpObjectItemSet = CreateNewItemSet(*pPool); ForceDefaultAttr(); } } const Rectangle& SdrAttrObj::GetSnapRect() const { if(bSnapRectDirty) { ((SdrAttrObj*)this)->RecalcSnapRect(); ((SdrAttrObj*)this)->bSnapRectDirty = FALSE; } return maSnapRect; } void SdrAttrObj::operator=(const SdrObject& rObj) { // call parent SdrObject::operator=(rObj); SdrAttrObj* pAO = PTR_CAST(SdrAttrObj, (SdrObject*)&rObj); if(pAO) { ImpDeleteItemSet(); if(pAO->mpObjectItemSet) mpObjectItemSet = pAO->mpObjectItemSet->Clone(TRUE); if(pAO->GetStyleSheet()) AddStyleSheet(pAO->GetStyleSheet(), TRUE); } } void SdrAttrObj::ReadData(const SdrObjIOHeader& rHead, SvStream& rIn) { if(rIn.GetError()) return; // call parent SdrObject::ReadData(rHead, rIn); SdrDownCompat aCompat(rIn, STREAM_READ); #ifdef DBG_UTIL aCompat.SetID("SdrAttrObj"); #endif SfxItemPool* pPool = GetItemPool(); if(pPool) { sal_uInt16 nSetID; // #89025# if mpObjectItemSet is set and contains items, it is because of ForceDefaultAttr() // and the items need to be deleted. if(mpObjectItemSet && mpObjectItemSet->Count()) mpObjectItemSet->ClearItem(0); // Do this initialization AFTER the above fix SfxItemSet aNewSet(GetItemSet()); if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = XATTRSET_LINE; const XLineAttrSetItem* pLineAttr = (const XLineAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pLineAttr) aNewSet.Put(pLineAttr->GetItemSet()); if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = XATTRSET_FILL; const XFillAttrSetItem* pFillAttr = (const XFillAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pFillAttr) aNewSet.Put(pFillAttr->GetItemSet()); if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = XATTRSET_TEXT; const XTextAttrSetItem* pTextAttr = (const XTextAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pTextAttr) aNewSet.Put(pTextAttr->GetItemSet()); if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = SDRATTRSET_SHADOW; const SdrShadowSetItem* pShadAttr = (const SdrShadowSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pShadAttr) aNewSet.Put(pShadAttr->GetItemSet()); if(rHead.GetVersion() >= 5) { if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = SDRATTRSET_OUTLINER; const SdrOutlinerSetItem* pOutlAttr = (const SdrOutlinerSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pOutlAttr) aNewSet.Put(pOutlAttr->GetItemSet()); } if(rHead.GetVersion() >= 6) { if(rHead.GetVersion() < 11) { sal_uInt16 nWhichDum; rIn >> nWhichDum; } nSetID = SDRATTRSET_MISC; const SdrMiscSetItem* pMiscAttr = (const SdrMiscSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0); if(pMiscAttr) aNewSet.Put(pMiscAttr->GetItemSet()); } SetItemSet(aNewSet); } else { // an den Surrogaten und ggf. auch Whiches vorbeiseeken // ganz zu anfang waren es 4 SetItems sal_uInt16 nAnz(4); if(rHead.GetVersion() >= 5) nAnz++; if(rHead.GetVersion() >= 6) nAnz++; nAnz *= sizeof(sal_uInt16); if(rHead.GetVersion() < 11) nAnz *= 2; rIn.SeekRel(nAnz); } // TextToContour: altes Format(Flag) in neues Format(Item) wandeln if(rHead.GetVersion() <= 4 && pPool) { SetItem(XFormTextStyleItem(XFT_NONE)); } // Fuer die StyleSheetgeschichte gehoert eigentlich auch noch eine // Versionsabfrage hierher. // Name und Familie des StyleSheet einlesen, in Pointer auf StyleSheet // umwandeln lassen (SB) XubString aStyleSheetName; SfxStyleFamily eFamily; sal_uInt16 nRead; // UNICODE: rIn>>aStyleSheetName; rIn.ReadByteString(aStyleSheetName); if(aStyleSheetName.Len()) { rIn >> nRead; eFamily = (SfxStyleFamily)(int)nRead; // ab Version 1 wird der CharacterSet gelesen, ab V11 nicht mehr if(rHead.GetVersion() > 0 && rHead.GetVersion() < 11) { sal_Int16 nCharSet; rIn >> nCharSet; //aStyleSheetName.Convert((CharSet)nCharSet); // nicht mehr noetig, da ab Vers 11 der CharSet bereits am // Stream gesetzt wird. } DBG_ASSERT(pModel, "SdrAttrObj::ReadData(): pModel=NULL, StyleSheet kann nicht gesetzt werden!"); if(pModel) { SfxStyleSheetBasePool *pPool = pModel->GetStyleSheetPool(); if(pPool) { SfxStyleSheet *pTmpStyleSheet = (SfxStyleSheet*)pPool->Find(aStyleSheetName, eFamily); DBG_ASSERT(pTmpStyleSheet, "SdrAttrObj::ReadData(): StyleSheet nicht gefunden"); if(pTmpStyleSheet) AddStyleSheet(pTmpStyleSheet, TRUE); } } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // pre- and postprocessing for objects for saving void SdrAttrObj::PreSave() { // call parent SdrObject::PreSave(); // prepare SetItems for storage const SfxItemSet& rSet = GetUnmergedItemSet(); const SfxItemSet* pParent = GetStyleSheet() ? &GetStyleSheet()->GetItemSet() : 0L; XLineAttrSetItem aLineAttr(rSet.GetPool()); aLineAttr.GetItemSet().Put(rSet); aLineAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aLineAttr); XFillAttrSetItem aFillAttr(rSet.GetPool()); aFillAttr.GetItemSet().Put(rSet); aFillAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aFillAttr); XTextAttrSetItem aTextAttr(rSet.GetPool()); aTextAttr.GetItemSet().Put(rSet); aTextAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aTextAttr); SdrShadowSetItem aShadAttr(rSet.GetPool()); aShadAttr.GetItemSet().Put(rSet); aShadAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aShadAttr); SdrOutlinerSetItem aOutlAttr(rSet.GetPool()); aOutlAttr.GetItemSet().Put(rSet); aOutlAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aOutlAttr); SdrMiscSetItem aMiscAttr(rSet.GetPool()); aMiscAttr.GetItemSet().Put(rSet); aMiscAttr.GetItemSet().SetParent(pParent); mpObjectItemSet->Put(aMiscAttr); } void SdrAttrObj::PostSave() { // call parent SdrObject::PostSave(); // remove SetItems from local itemset ((SdrAttrObj*)this)->ImpForceItemSet(); mpObjectItemSet->ClearItem(XATTRSET_LINE); mpObjectItemSet->ClearItem(XATTRSET_FILL); mpObjectItemSet->ClearItem(XATTRSET_TEXT); mpObjectItemSet->ClearItem(SDRATTRSET_SHADOW); mpObjectItemSet->ClearItem(SDRATTRSET_OUTLINER); mpObjectItemSet->ClearItem(SDRATTRSET_MISC); } //////////////////////////////////////////////////////////////////////////////////////////////////// void SdrAttrObj::WriteData(SvStream& rOut) const { // call parent SdrObject::WriteData(rOut); // Fuer Abwaertskompatibilitaet (Lesen neuer Daten mit altem Code) SdrDownCompat aCompat(rOut, STREAM_WRITE); #ifdef DBG_UTIL aCompat.SetID("SdrAttrObj"); #endif SfxItemPool* pPool = GetItemPool(); if(pPool) { const SfxItemSet& rSet = GetUnmergedItemSet(); pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_LINE)); pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_FILL)); pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_TEXT)); pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_SHADOW)); pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_OUTLINER)); pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_MISC)); } else { rOut << sal_uInt16(SFX_ITEMS_NULL); rOut << sal_uInt16(SFX_ITEMS_NULL); rOut << sal_uInt16(SFX_ITEMS_NULL); rOut << sal_uInt16(SFX_ITEMS_NULL); rOut << sal_uInt16(SFX_ITEMS_NULL); rOut << sal_uInt16(SFX_ITEMS_NULL); } // StyleSheet-Pointer als Name, Familie abspeichern // wenn kein StyleSheet vorhanden: leeren String speichern if(GetStyleSheet()) { // UNICODE: rOut << pStyleSheet->GetName(); rOut.WriteByteString(GetStyleSheet()->GetName()); rOut << (sal_uInt16)(int)(GetStyleSheet()->GetFamily()); } else { // UNICODE: rOut << String(); rOut.WriteByteString(String()); } } static void ImpScaleItemSet(SfxItemSet& rSet, const Fraction& rScale) { sal_Int32 nMul(rScale.GetNumerator()); sal_Int32 nDiv(rScale.GetDenominator()); if(!rScale.IsValid() || !nDiv) return; SfxWhichIter aIter(rSet); sal_uInt16 nWhich(aIter.FirstWhich()); const SfxPoolItem *pItem = NULL; while(nWhich) { if(SFX_ITEM_SET == rSet.GetItemState(nWhich, FALSE, &pItem)) { if(pItem->HasMetrics()) { SfxPoolItem* pNewItem = pItem->Clone(); pNewItem->ScaleMetrics(nMul, nDiv); rSet.Put(*pNewItem); } } nWhich = aIter.NextWhich(); } } void SdrAttrObj::SetModel(SdrModel* pNewModel) { SdrModel* pOldModel = pModel; // test for correct pool in ItemSet; move to new pool if necessary if(pNewModel && mpObjectItemSet && mpObjectItemSet->GetPool() != &pNewModel->GetItemPool()) MigrateItemPool(mpObjectItemSet->GetPool(), &pNewModel->GetItemPool(), pNewModel); // call parent SdrObject::SetModel(pNewModel); if(pOldModel != pNewModel && pNewModel && !pNewModel->IsLoading()) { // fuer ein bereits "lebendes" Model die Attribute von einem Pool in den anderen schieben if(pOldModel) { // Checken, ob sich die ScaleUnit geaendert hat. // Denn dann muessen naemlich alle MetrikItems umgerechnet werden. MapUnit aOldUnit(pOldModel->GetScaleUnit()); MapUnit aNewUnit(pNewModel->GetScaleUnit()); BOOL bScaleUnitChanged(aNewUnit != aOldUnit); Fraction aMetricFactor; if(bScaleUnitChanged) { aMetricFactor = GetMapFactor(aOldUnit, aNewUnit).X(); if(mpObjectItemSet) { // #75371# To have a notify on scaling, do it on a copy of the // local ItemSet and set this one then SfxItemSet aItemSet(*mpObjectItemSet); ImpScaleItemSet(aItemSet, aMetricFactor); SetItemSet(aItemSet); } } // Und nun alle Items auf die das Obj verweisst aus // dem alten Pools raus und in den neuen rein. SfxStyleSheet* pOldStyleSheet = GetStyleSheet(); // ***** StyleSheets Anfang ***** // ggfs. StyleSheet und dessen Parents kopieren // Follows werden nicht beruecksichtigt (ganz wie im Writer) if(pOldStyleSheet) { SfxStyleSheetBase* pSheet = pOldStyleSheet; SfxStyleSheetBasePool* pOldPool = pOldModel->GetStyleSheetPool(); SfxStyleSheetBasePool* pNewPool = pModel->GetStyleSheetPool(); DBG_ASSERT(pOldPool, "SdrAttrObj::SetModel(): Objekt hat StyleSheet aber keinen StyleSheetPool am SdrModel"); if(pOldPool && pNewPool) { // Liste der zu kopierenden Vorlagen List aList; SfxStyleSheetBase* pAnchor = NULL; while(pSheet) { pAnchor = pNewPool->Find(pSheet->GetName(), pSheet->GetFamily()); if(!pAnchor) { aList.Insert(pSheet, LIST_APPEND); pSheet = pOldPool->Find(pSheet->GetParent(), pSheet->GetFamily()); } else { // die gesuchte Vorlage gibt's schon pSheet = NULL; } } // kopieren und Parents der Kopien setzen pSheet = (SfxStyleSheetBase*)aList.First(); SfxStyleSheetBase* pNewSheet = NULL; SfxStyleSheetBase* pLastSheet = NULL; SfxStyleSheetBase* pForThisObject = NULL; while(pSheet) { pNewSheet = &pNewPool->Make(pSheet->GetName(), pSheet->GetFamily(), pSheet->GetMask()); pNewSheet->GetItemSet().Put(pSheet->GetItemSet(), FALSE); if(bScaleUnitChanged) ImpScaleItemSet(pNewSheet->GetItemSet(), aMetricFactor); if(pLastSheet) pLastSheet->SetParent(pNewSheet->GetName()); if(!pForThisObject) pForThisObject = pNewSheet; pLastSheet = pNewSheet; pSheet = (SfxStyleSheetBase*)aList.Next(); } // Veknuepfung mit der im Zielpool gefundenen Vorlage if(pAnchor && pLastSheet) pLastSheet->SetParent(pAnchor->GetName()); // falls die Liste leer war (alle Vorlagen schon im Zielpool // vorhanden) ist pForThisObject noch nicht gesetzt if(!pForThisObject && pAnchor) pForThisObject = pAnchor; // am alten StyleSheet ab- und am neuen anmelden if(GetStyleSheet() != pForThisObject) { RemoveStyleSheet(); AddStyleSheet((SfxStyleSheet*)pForThisObject, TRUE); } } else { // Aha, im neuen Model gibt's also kein StyleSheetPool // also setzte ich "einfach" alle Attribute des alten StyleSheets hart List aList; const SfxItemSet* pItemSet = &pOldStyleSheet->GetItemSet(); while(pItemSet) { aList.Insert((void*)pItemSet, CONTAINER_APPEND); pItemSet = pItemSet->GetParent(); } SfxItemSet* pNewSet = CreateNewItemSet(pNewModel->GetItemPool()); pItemSet = (SfxItemSet*)aList.Last(); while(pItemSet) { pNewSet->Put(*pItemSet); pItemSet = (SfxItemSet*)aList.Prev(); } // Attribute, die schon vorher hart gesetzt // waren muessen aber erhalten bleiben: if(mpObjectItemSet) { SfxWhichIter aIter(*mpObjectItemSet); sal_uInt16 nWhich = aIter.FirstWhich(); while(nWhich) { if(mpObjectItemSet->GetItemState(nWhich, FALSE) == SFX_ITEM_SET) pNewSet->Put(mpObjectItemSet->Get(nWhich)); nWhich = aIter.NextWhich(); } } if(bScaleUnitChanged) ImpScaleItemSet(*pNewSet, aMetricFactor); ImpDeleteItemSet(); mpObjectItemSet = pNewSet; } } // ***** StyleSheets Ende ***** } // Jedes Objekt bekommt initial den DefaultStyleSheet // des Model, falls noch kein StyleSheet gesetzt. if(mpObjectItemSet && !GetStyleSheet() && pModel && !pModel->IsLoading()) NbcSetStyleSheet(pModel->GetDefaultStyleSheet(), TRUE); /* this code was removed because NbcSetStyleSheet called with TRUE does not alter the hard attributes. So they don't need to be restored, a useless process that cost us up to 20% for xml import. Also there is a memory leek with aSet.Put( *pItem->Clone() ); { SfxStyleSheet* pDefSS = pModel->GetDefaultStyleSheet(); if(pDefSS) { SfxItemPool* pPool = GetItemPool(); if ( pPool ) { // Take hard attributes SfxItemSet aSet(*pPool, SDRATTR_START,SDRATTR_NOTPERSIST_FIRST-1, SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END, EE_ITEMS_START,EE_ITEMS_END, 0,0); const SfxItemSet& rItemSet = GetItemSet(); SfxWhichIter aIter( rItemSet ); sal_uInt16 nWhich( aIter.FirstWhich() ); const SfxPoolItem* pItem = NULL; while( nWhich ) { if( SFX_ITEM_SET == rItemSet.GetItemState( nWhich, FALSE, &pItem ) ) aSet.Put( *pItem->Clone() ); nWhich = aIter.NextWhich(); } // Set the StyleSheet NbcSetStyleSheet(pDefSS, TRUE); // Set the hard attributes SetItemSet( aSet ); } else NbcSetStyleSheet(pDefSS, TRUE); } } */ } } void SdrAttrObj::ForceDefaultAttr() { SdrTextObj* pText = PTR_CAST(SdrTextObj, this); BOOL bTextFrame(pText && pText->IsTextFrame()); ImpForceItemSet(); if(bTextFrame) { SdrCaptionObj* pCapt = PTR_CAST(SdrCaptionObj, this); BOOL bCaption(pCapt != 0L); if(!bCaption) mpObjectItemSet->Put(XLineStyleItem(XLINE_NONE)); mpObjectItemSet->Put(XFillColorItem(String(), Color(COL_WHITE))); mpObjectItemSet->Put(XFillStyleItem(XFILL_NONE)); } else { mpObjectItemSet->Put(SvxAdjustItem(SVX_ADJUST_CENTER)); mpObjectItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); mpObjectItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); } } //////////////////////////////////////////////////////////////////////////////////////////////////// // ItemSet access const SfxItemSet& SdrAttrObj::GetItemSet() const { ((SdrAttrObj*)this)->ImpForceItemSet(); return *mpObjectItemSet; } SfxItemSet* SdrAttrObj::CreateNewItemSet(SfxItemPool& rPool) { // include ALL items, 2D and 3D return new SfxItemSet(rPool, // ranges from SdrAttrObj SDRATTR_START, SDRATTRSET_SHADOW, SDRATTRSET_OUTLINER, SDRATTRSET_MISC, SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION, // outliner and end EE_ITEMS_START, EE_ITEMS_END, 0, 0); } //////////////////////////////////////////////////////////////////////////////////////////////////// // syntactical sugar for ItemSet accesses const SfxItemSet& SdrAttrObj::GetUnmergedItemSet() const { return SdrAttrObj::GetItemSet(); } void SdrAttrObj::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem) { if(pNewItem) { const SfxPoolItem* pItem = pNewItem; switch( nWhich ) { case XATTR_FILLBITMAP: pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_LINEDASH: pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_LINESTART: pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_LINEEND: pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_FILLGRADIENT: pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_FILLFLOATTRANSPARENCE: // #85953# allow all kinds of XFillFloatTransparenceItem to be set pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pModel ); break; case XATTR_FILLHATCH: pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pModel ); break; } // set item if( pItem ) { ((SdrAttrObj*)this)->ImpForceItemSet(); mpObjectItemSet->Put(*pItem); // delete item if it was a generated one if( pItem != pNewItem) delete (SfxPoolItem*)pItem; } } else { // clear item if(mpObjectItemSet) { mpObjectItemSet->ClearItem(nWhich); } } } void SdrAttrObj::ItemSetChanged(const SfxItemSet& rSet) { // call parent SdrObject::ItemSetChanged(rSet); // own modifications bBoundRectDirty = TRUE; SetRectsDirty(TRUE); SetChanged(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void __EXPORT SdrAttrObj::SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType) { SfxSimpleHint *pSimple = PTR_CAST(SfxSimpleHint, &rHint); BOOL bDataChg(pSimple && SFX_HINT_DATACHANGED == pSimple->GetId()); SfxStyleSheetHint *pStyleHint = PTR_CAST(SfxStyleSheetHint, &rHint); BOOL bDying(pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet() && ( SFX_STYLESHEET_INDESTRUCTION == pStyleHint->GetHint() || SFX_STYLESHEET_ERASED == pStyleHint->GetHint() )); if(bDataChg || bDying) { Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetBoundRect(); SfxStyleSheet* pNewStSh = NULL; BOOL bBoundRectDirty0 = bBoundRectDirty; if(bDying) { // wenn es einen Parent gibt, wird jetzt der genommen if(pModel && HAS_BASE(SfxStyleSheet, GetStyleSheet())) { // Sonst ist pStyleSheet schon zu weit weggestorben pNewStSh = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find( GetStyleSheet()->GetParent(), GetStyleSheet()->GetFamily()); } // wenn es keinen Parent gibt, nehmen wir die Standardvorlage if(!pNewStSh && pModel) pNewStSh = pModel->GetDefaultStyleSheet(); // alten StyleSheet vor SendRepaintBroadcast entfernen #42276# RemoveStyleSheet(); // setzt bBoundRectDirty=TRUE } if(!bBoundRectDirty0) { bBoundRectDirty = FALSE; // fuer Broadcast mit dem alten Rect if(pPage && pPage->IsInserted()) SendRepaintBroadcast(); // Erstmal mit dem alten Rect bBoundRectDirty = TRUE; SetRectsDirty(TRUE); // Durch Vorlagenloeschung evtl. andere Linienbreite } if(pNewStSh && !bDying) AddStyleSheet(pNewStSh, TRUE); if(pPage && pPage->IsInserted()) SendRepaintBroadcast(); SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0); } } SfxStyleSheet* SdrAttrObj::GetStyleSheet() const { return mpStyleSheet; } void SdrAttrObj::RemoveStyleSheet() { // Typ checken, weil bei dying sich der Typ abbaut (bis zum Broadcaster runter) if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet)) { EndListening(*mpStyleSheet); EndListening(mpStyleSheet->GetPool()); // das ItemSet der Vorlage ist jetzt nicht mehr Parent der // eigenen ItemSets if(mpObjectItemSet) mpObjectItemSet->SetParent(NULL); bBoundRectDirty = TRUE; SetRectsDirty(TRUE); } mpStyleSheet = NULL; } void SdrAttrObj::AddStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr) { // old StyleSheet is deleted DBG_ASSERT(!mpStyleSheet, "Old style sheet not deleted before setting new one (?)"); if(pNewStyleSheet) { mpStyleSheet = pNewStyleSheet; // ItemSet is needed here, force it ImpForceItemSet(); // als Listener anmelden StartListening(pNewStyleSheet->GetPool()); StartListening(*pNewStyleSheet); // harte Attributierung dort loeschen, wo was in der Vorlage steht if(!bDontRemoveHardAttr) { const SfxItemSet& rStyle = pNewStyleSheet->GetItemSet(); SfxWhichIter aIter(rStyle); sal_uInt16 nWhich = aIter.FirstWhich(); while(nWhich) { if(SFX_ITEM_SET == rStyle.GetItemState(nWhich)) mpObjectItemSet->ClearItem(nWhich); nWhich = aIter.NextWhich(); } } // set new stylesheet as parent mpObjectItemSet->SetParent(&pNewStyleSheet->GetItemSet()); } } void SdrAttrObj::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr) { RemoveStyleSheet(); AddStyleSheet(pNewStyleSheet, bDontRemoveHardAttr); bBoundRectDirty = TRUE; SetRectsDirty(TRUE); } void SdrAttrObj::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr) { Rectangle aBoundRect0; if(pUserCall) aBoundRect0 = GetBoundRect(); SendRepaintBroadcast(); NbcSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr); SetChanged(); SendRepaintBroadcast(); SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0); } INT32 SdrAttrObj::ImpGetLineWdt() const { const SfxItemSet& rSet = GetItemSet(); XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue(); if(XLINE_NONE == eLine) return 0; // Garkeine Linie da. sal_Int32 nWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); return nWdt; } INT32 SdrAttrObj::ImpGetLineEndAdd() const { const SfxItemSet& rSet = GetItemSet(); BOOL bStartSet(TRUE); BOOL bEndSet(TRUE); if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINESTART)) { String aStr(((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetName()); if(!aStr.Len()) bStartSet = FALSE; } if(rSet.GetItemState(XATTR_LINEEND) != SFX_ITEM_DONTCARE) { String aStr(((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetName()); if(!aStr.Len()) bEndSet = FALSE; } BOOL bLineEndSet = bStartSet || bEndSet; XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue(); if(XLINE_NONE == eLine) return 0; // Garkeine Linie da. // Strichstaerke sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); sal_Int32 nSttWdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); if(nSttWdt < 0) nSttWdt = -nLineWdt * nSttWdt / 100; if(!bLineEndSet) nSttWdt = 0; BOOL bSttCenter = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue(); sal_Int32 nSttHgt = 0; if(bSttCenter) { // Linienende steht um die Haelfe ueber XPolygon aSttPoly(((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetValue()); nSttHgt = XOutputDevice::InitLineStartEnd(aSttPoly, nSttWdt, bSttCenter); // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe } nSttWdt++; nSttWdt /= 2; // Lieber etwas mehr, dafuer keine Wurzel ziehen long nSttAdd = Max(nSttWdt, nSttHgt); nSttAdd *= 3; nSttAdd /= 2; long nEndWdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue(); if(nEndWdt < 0) nEndWdt = -nLineWdt * nEndWdt / 100; // <0 = relativ if(!bLineEndSet) nEndWdt = 0; BOOL bEndCenter = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue(); sal_Int32 nEndHgt = 0; if(bEndCenter) { // Linienende steht um die Haelfe ueber XPolygon aEndPoly(((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetValue()); nEndHgt = XOutputDevice::InitLineStartEnd(aEndPoly, nEndWdt, bEndCenter); // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe } nEndWdt++; nEndWdt /= 2; // Lieber etwas mehr, dafuer keine Wurzel ziehen sal_Int32 nEndAdd = Max(nEndWdt, nEndHgt); nEndAdd *= 3; nEndAdd /= 2; return Max(nSttAdd, nEndAdd); } ////////////////////////////////////////////////////////////////////////////// FASTBOOL SdrAttrObj::ImpLineEndHitTest(const Point& rEndPt, double nSin, double nCos, FASTBOOL bStart, const Point& rHit, USHORT nTol) const { const SfxItemSet& rSet = GetItemSet(); sal_Int32 nWdt = 0; BOOL bCenter = FALSE; XPolygon aXPoly; if(bStart) { nWdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue(); bCenter = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue(); aXPoly = ((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetValue(); } else { nWdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue(); bCenter = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue(); aXPoly = ((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetValue(); } if(nWdt < 0) { sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); // Strichstaerke nWdt = -nLineWdt * nWdt / 100; // <0 = relativ } // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe XOutputDevice::InitLineStartEnd(aXPoly, nWdt, bCenter); RotateXPoly(aXPoly, Point(), nSin, nCos); Point aHit(rHit); aHit -= rEndPt; Rectangle aHitRect(aHit.X() - nTol, aHit.Y() - nTol, aHit.X() + nTol, aHit.Y() + nTol); FASTBOOL bHit = IsRectTouchesPoly(XOutCreatePolygon(aXPoly, NULL), aHitRect); return bHit; } FASTBOOL SdrAttrObj::ImpGetShadowDist(sal_Int32& nXDist, sal_Int32& nYDist) const { const SfxItemSet& rSet = GetItemSet(); nXDist = 0L; nYDist = 0L; BOOL bShadOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue(); if(bShadOn) { nXDist = ((SdrShadowXDistItem&)(rSet.Get(SDRATTR_SHADOWXDIST))).GetValue(); nYDist = ((SdrShadowYDistItem&)(rSet.Get(SDRATTR_SHADOWYDIST))).GetValue(); return TRUE; } return FALSE; } void SdrAttrObj::ImpAddShadowToBoundRect() { sal_Int32 nXDist; sal_Int32 nYDist; if(ImpGetShadowDist(nXDist, nYDist)) { if(nXDist > 0) aOutRect.Right() += nXDist; else aOutRect.Left() += nXDist; if(nYDist > 0) aOutRect.Bottom() += nYDist; else aOutRect.Top() += nYDist; } } FASTBOOL SdrAttrObj::ImpSetShadowAttributes(ExtOutputDevice& rXOut, FASTBOOL bNoFill) const { const SfxItemSet& rSet = GetItemSet(); BOOL bShadOn=((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue(); if(bShadOn) { // LineAttr for shadow no longer necessary, lines and line shadows are drawn in Paint() // routines individually (grep for CreateLinePoly()) // // if (pLineAttr!=NULL) { // XLineAttrSetItem aL(*pLineAttr); // aL.GetItemSet().Put(XLineColorItem(String(),aShadCol)); // aL.GetItemSet().Put(XLineTransparenceItem(nTransp)); // rXOut.SetLineAttr(aL); // } if(!bNoFill) { const SdrShadowColorItem& rShadColItem = ((const SdrShadowColorItem&)(rSet.Get(SDRATTR_SHADOWCOLOR))); Color aShadCol(rShadColItem.GetValue()); sal_uInt16 nTransp = ((const SdrShadowTransparenceItem&)(rSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue(); XFillStyle eStyle = ((const XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue(); BOOL bFillBackground = ((const XFillBackgroundItem&)(rSet.Get(XATTR_FILLBACKGROUND))).GetValue(); SfxItemSet aSet(rSet); if(eStyle==XFILL_HATCH && !bFillBackground) { // #41666# XHatch aHatch = ((XFillHatchItem&)(rSet.Get(XATTR_FILLHATCH))).GetValue(); aHatch.SetColor(aShadCol); aSet.Put(XFillHatchItem(String(), aHatch)); } else { if(eStyle != XFILL_NONE && eStyle != XFILL_SOLID) { // also fuer Gradient und Bitmap aSet.Put(XFillStyleItem(XFILL_SOLID)); } aSet.Put(XFillColorItem(String(),aShadCol)); // #92183# set XFillTransparenceItem only when no FloatTransparence is used, // else the OutDev will use the wrong method if(nTransp) { const XFillFloatTransparenceItem& rFillFloatTransparence = (const XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE); if(!rFillFloatTransparence.IsEnabled()) aSet.Put(XFillTransparenceItem(nTransp)); } } rXOut.SetFillAttr(aSet); } return TRUE; } return FALSE; } // ItemPool fuer dieses Objekt wechseln void SdrAttrObj::MigrateItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel) { if(pSrcPool && pDestPool && (pSrcPool != pDestPool)) { // call parent SdrObject::MigrateItemPool(pSrcPool, pDestPool, pNewModel); // eigene Reaktion if(pDestPool && pSrcPool && (pDestPool != pSrcPool)) { if(mpObjectItemSet) { if( pNewModel == NULL ) pNewModel = GetModel(); // migrate ItemSet to new pool. Scaling is NOT necessary // because this functionality is used by UNDO only. Thus // objects and ItemSets would be moved back to their original // pool before usage. SfxItemSet* pOldSet = mpObjectItemSet; SfxStyleSheet* pStySheet = GetStyleSheet(); if(GetStyleSheet()) RemoveStyleSheet(); mpObjectItemSet = CreateNewItemSet(*pDestPool); SfxWhichIter aWhichIter(*pOldSet); sal_uInt16 nWhich(aWhichIter.FirstWhich()); const SfxPoolItem *pPoolItem; while(nWhich) { if(SFX_ITEM_SET == pOldSet->GetItemState(nWhich, FALSE, &pPoolItem)) { const SfxPoolItem* pItem = pPoolItem; switch( nWhich ) { case XATTR_FILLBITMAP: pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_LINEDASH: pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_LINESTART: pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_LINEEND: pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_FILLGRADIENT: pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_FILLFLOATTRANSPARENCE: // #85953# allow all kinds of XFillFloatTransparenceItem to be set pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pNewModel ); break; case XATTR_FILLHATCH: pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pNewModel ); break; } // set item if( pItem ) { mpObjectItemSet->Put(*pItem); // delete item if it was a generated one if( pItem != pPoolItem) delete (SfxPoolItem*)pItem; } } nWhich = aWhichIter.NextWhich(); } // set stylesheet (if used) if(pStySheet) AddStyleSheet(pStySheet, TRUE); delete pOldSet; } } } } BOOL SdrAttrObj::HasFill() const { return (!bClosedObj) ? FALSE : ((XFillStyleItem&)(GetItem(XATTR_FILLSTYLE))).GetValue()!=XFILL_NONE; } BOOL SdrAttrObj::HasLine() const { return ((XLineStyleItem&)(GetItem(XATTR_LINESTYLE))).GetValue()!=XLINE_NONE; } // #94547# Have to re-activate more performant, but corrected version. // This is necessary since SetItemSet() of the old implementation calls // ItemSetChanged() which replaces in textobjects all text items which // is wrong behaviour for BurnInStyleSheet. void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly ) { if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet)) { // prepare copied, new itemset, but WITHOUT parent ImpForceItemSet(); SfxItemSet* pDestItemSet = new SfxItemSet(*mpObjectItemSet); pDestItemSet->SetParent(0L); // pepare forgetting the current stylesheet like in RemoveStyleSheet() EndListening(*mpStyleSheet); EndListening(mpStyleSheet->GetPool()); // get itemset of the stylesheet const SfxItemSet& rSet = mpStyleSheet->GetItemSet(); // prepare the iter; use the mpObjectItemSet which may have less // WhichIDs than the style. SfxWhichIter aIter(*pDestItemSet); sal_uInt16 nWhich(aIter.FirstWhich()); const SfxPoolItem *pItem = NULL; // set all attributes of the stylesheet at the new itemset while(nWhich) { if(SFX_ITEM_SET == rSet.GetItemState(nWhich, TRUE, &pItem)) pDestItemSet->Put(*pItem); nWhich = aIter.NextWhich(); } // prepare 2nd loop nWhich = aIter.FirstWhich(); // now set all hard attributes of the current at the new itemset while(nWhich) { if(SFX_ITEM_SET == mpObjectItemSet->GetItemState(nWhich, FALSE, &pItem)) pDestItemSet->Put(*pItem); nWhich = aIter.NextWhich(); } // replace itemsets delete mpObjectItemSet; mpObjectItemSet = pDestItemSet; // set necessary changes like in RemoveStyleSheet() bBoundRectDirty = TRUE; SetRectsDirty(TRUE); mpStyleSheet = NULL; } } // #91695# back to corrected old version. Have to check new version again for later builds. //void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly ) //{ // SfxItemPool* pPool = GetItemPool(); // if ( pPool && mpStyleSheet ) // { // // Get StyleSheet attributes // SfxItemSet aSet(*pPool, // SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1, // SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END, // EE_ITEMS_START,EE_ITEMS_END, // 0,0); // // SfxWhichIter aIter( mpStyleSheet->GetItemSet() ); // sal_uInt16 nWhich( aIter.FirstWhich() ); // const SfxPoolItem* pItem = NULL; // // while( nWhich ) // { // if( SFX_ITEM_SET == mpStyleSheet->GetItemSet().GetItemState(nWhich, TRUE, &pItem) ) // aSet.Put( *pItem ); // // nWhich = aIter.NextWhich(); // } // // SfxWhichIter aHardAttrIter( GetItemSet() ); // nWhich = aHardAttrIter.FirstWhich(); // // while( nWhich ) // { // if( SFX_ITEM_SET == GetItemSet().GetItemState(nWhich, FALSE, &pItem) ) // aSet.Put( *pItem ); // // nWhich = aHardAttrIter.NextWhich(); // } // // // Set StyleSheet attributes as hard attributes // SetItemSet( aSet ); // } //} /* void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly ) { // #89025# Added more performant implementation if(mpStyleSheet) { const SfxItemSet& rSet = mpStyleSheet->GetItemSet(); SfxWhichIter aIter(rSet); sal_uInt16 nWhich(aIter.FirstWhich()); const SfxPoolItem *pItem = NULL; ImpForceItemSet(); const SfxItemSet* pParentSet = mpObjectItemSet->GetParent(); if(pParentSet != 0L) mpObjectItemSet->SetParent(0L); while(nWhich) { if(SFX_ITEM_SET == rSet.GetItemState(nWhich, TRUE, &pItem)) mpObjectItemSet->Put(*pItem); nWhich = aIter.NextWhich(); } if(pParentSet != 0L) mpObjectItemSet->SetParent(pParentSet); } } */