summaryrefslogtreecommitdiff
path: root/svx/source/sdr/properties/attributeproperties.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/sdr/properties/attributeproperties.cxx')
-rw-r--r--svx/source/sdr/properties/attributeproperties.cxx628
1 files changed, 628 insertions, 0 deletions
diff --git a/svx/source/sdr/properties/attributeproperties.cxx b/svx/source/sdr/properties/attributeproperties.cxx
new file mode 100644
index 000000000000..0f3325a0027e
--- /dev/null
+++ b/svx/source/sdr/properties/attributeproperties.cxx
@@ -0,0 +1,628 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/sdr/properties/attributeproperties.hxx>
+#include <svx/sdr/properties/itemsettools.hxx>
+#include <tools/debug.hxx>
+#include <svl/itemset.hxx>
+#include <svl/style.hxx>
+#include <svl/whiter.hxx>
+#include <svl/poolitem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svddef.hxx>
+#include <svx/xit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/xflhtit.hxx>
+#include <svx/xlnasit.hxx>
+#include <svx/xflasit.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/svdpage.hxx>
+
+// #114265#
+#include <svl/smplhint.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace sdr
+{
+ namespace properties
+ {
+ void AttributeProperties::ImpAddStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
+ {
+ // test if old StyleSheet is cleared, else it would be lost
+ // after this method -> memory leak (!)
+ DBG_ASSERT(!mpStyleSheet, "Old style sheet not deleted before setting new one (!)");
+
+ if(pNewStyleSheet)
+ {
+ mpStyleSheet = pNewStyleSheet;
+
+ // local ItemSet is needed here, force it
+ GetObjectItemSet();
+
+ // register as listener
+ StartListening(pNewStyleSheet->GetPool());
+ StartListening(*pNewStyleSheet);
+
+ // Delete hard attributes where items are set in the style sheet
+ if(!bDontRemoveHardAttr)
+ {
+ const SfxItemSet& rStyle = pNewStyleSheet->GetItemSet();
+ SfxWhichIter aIter(rStyle);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ if(SFX_ITEM_SET == rStyle.GetItemState(nWhich))
+ {
+ mpItemSet->ClearItem(nWhich);
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+ }
+
+ // set new stylesheet as parent
+ mpItemSet->SetParent(&pNewStyleSheet->GetItemSet());
+ }
+ }
+
+ void AttributeProperties::ImpRemoveStyleSheet()
+ {
+ // Check type since it is destroyed when the type is deleted
+ if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
+ {
+ EndListening(*mpStyleSheet);
+ EndListening(mpStyleSheet->GetPool());
+
+ // reset parent of ItemSet
+ if(mpItemSet)
+ {
+ mpItemSet->SetParent(0L);
+ }
+
+ SdrObject& rObj = GetSdrObject();
+ rObj.SetBoundRectDirty();
+ rObj.SetRectsDirty(sal_True);
+ }
+
+ mpStyleSheet = 0L;
+ }
+
+ // create a new itemset
+ SfxItemSet& AttributeProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
+ {
+ return *(new SfxItemSet(rPool,
+
+ // ranges from SdrAttrObj
+ SDRATTR_START, SDRATTR_SHADOW_LAST,
+ SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
+ SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
+
+ // end
+ 0, 0));
+ }
+
+ AttributeProperties::AttributeProperties(SdrObject& rObj)
+ : DefaultProperties(rObj),
+ mpStyleSheet(0L)
+ {
+ }
+
+ AttributeProperties::AttributeProperties(const AttributeProperties& rProps, SdrObject& rObj)
+ : DefaultProperties(rProps, rObj),
+ mpStyleSheet(0L)
+ {
+ if(rProps.GetStyleSheet())
+ {
+ ImpAddStyleSheet(rProps.GetStyleSheet(), sal_True);
+ }
+ }
+
+ AttributeProperties::~AttributeProperties()
+ {
+ ImpRemoveStyleSheet();
+ }
+
+ BaseProperties& AttributeProperties::Clone(SdrObject& rObj) const
+ {
+ return *(new AttributeProperties(*this, rObj));
+ }
+
+ void AttributeProperties::ItemSetChanged(const SfxItemSet& /*rSet*/)
+ {
+ // own modifications
+ SdrObject& rObj = GetSdrObject();
+
+ rObj.SetBoundRectDirty();
+ rObj.SetRectsDirty(sal_True);
+ rObj.SetChanged();
+ }
+
+ void AttributeProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
+ {
+ if(pNewItem)
+ {
+ const SfxPoolItem* pItem = pNewItem;
+ SdrModel* pModel = GetSdrObject().GetModel();
+
+ 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)
+ {
+ // force ItemSet
+ GetObjectItemSet();
+ mpItemSet->Put(*pItem);
+
+ // delete item if it was a generated one
+ if(pItem != pNewItem)
+ {
+ delete (SfxPoolItem*)pItem;
+ }
+ }
+ }
+ else
+ {
+ // clear item if ItemSet exists
+ if(mpItemSet)
+ {
+ mpItemSet->ClearItem(nWhich);
+ }
+ }
+ }
+
+ void AttributeProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
+ {
+ ImpRemoveStyleSheet();
+ ImpAddStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
+
+ SdrObject& rObj = GetSdrObject();
+ rObj.SetBoundRectDirty();
+ rObj.SetRectsDirty(sal_True);
+ }
+
+ SfxStyleSheet* AttributeProperties::GetStyleSheet() const
+ {
+ return mpStyleSheet;
+ }
+
+ void AttributeProperties::MoveToItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel)
+ {
+ OSL_ASSERT(pNewModel!=NULL);
+
+ if(pSrcPool && pDestPool && (pSrcPool != pDestPool))
+ {
+ if(mpItemSet)
+ {
+ // 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 = mpItemSet;
+ SfxStyleSheet* pStySheet = GetStyleSheet();
+
+ if(pStySheet)
+ {
+ ImpRemoveStyleSheet();
+ }
+
+ mpItemSet = mpItemSet->Clone(FALSE, pDestPool);
+ GetSdrObject().GetModel()->MigrateItemSet(pOldSet, mpItemSet, pNewModel);
+
+ // set stylesheet (if used)
+ if(pStySheet)
+ {
+ // #i109515#
+ SfxItemPool* pStyleSheetPool = &pStySheet->GetPool().GetPool();
+
+ if(pStyleSheetPool == pDestPool)
+ {
+ // just re-set stylesheet
+ ImpAddStyleSheet(pStySheet, sal_True);
+ }
+ else
+ {
+ // StyleSheet is NOT from the correct pool.
+ // Look one up in the right pool with the same
+ // name or use the default.
+
+ // Look up the style in the new document.
+ OSL_ASSERT(pNewModel->GetStyleSheetPool() != NULL);
+ SfxStyleSheet* pNewStyleSheet = dynamic_cast<SfxStyleSheet*>(
+ pNewModel->GetStyleSheetPool()->Find(
+ pStySheet->GetName(),
+ SFX_STYLE_FAMILY_ALL));
+ if (pNewStyleSheet == NULL
+ || &pNewStyleSheet->GetPool().GetPool() != pDestPool)
+ {
+ // There is no copy of the style in the new
+ // document. Use the default as a fallback.
+ pNewStyleSheet = pNewModel->GetDefaultStyleSheet();
+ }
+ ImpAddStyleSheet(pNewStyleSheet, sal_True);
+ }
+ }
+
+ delete pOldSet;
+ }
+ }
+ }
+
+ void AttributeProperties::SetModel(SdrModel* pOldModel, SdrModel* pNewModel)
+ {
+ if(pOldModel != pNewModel && pNewModel && !pNewModel->IsLoading())
+ {
+ // For a living model move the items from one pool to the other
+ if(pOldModel)
+ {
+ // If metric has changed, scale items.
+ MapUnit aOldUnit(pOldModel->GetScaleUnit());
+ MapUnit aNewUnit(pNewModel->GetScaleUnit());
+ sal_Bool bScaleUnitChanged(aNewUnit != aOldUnit);
+ Fraction aMetricFactor;
+
+ if(bScaleUnitChanged)
+ {
+ aMetricFactor = GetMapFactor(aOldUnit, aNewUnit).X();
+ Scale(aMetricFactor);
+ }
+
+ // Move all styles which are used by the object to the new
+ // StyleSheet pool
+ SfxStyleSheet* pOldStyleSheet = GetStyleSheet();
+
+ if(pOldStyleSheet)
+ {
+ SfxStyleSheetBase* pSheet = pOldStyleSheet;
+ SfxStyleSheetBasePool* pOldPool = pOldModel->GetStyleSheetPool();
+ SfxStyleSheetBasePool* pNewPool = pNewModel->GetStyleSheetPool();
+ DBG_ASSERT(pOldPool, "Properties::SetModel(): Object has StyleSheet but no StyleSheetPool (!)");
+
+ if(pOldPool && pNewPool)
+ {
+ // build a list of to-be-copied Styles
+ List aList;
+ SfxStyleSheetBase* pAnchor = 0L;
+
+ while(pSheet)
+ {
+ pAnchor = pNewPool->Find(pSheet->GetName(), pSheet->GetFamily());
+
+ if(!pAnchor)
+ {
+ aList.Insert(pSheet, LIST_APPEND);
+ pSheet = pOldPool->Find(pSheet->GetParent(), pSheet->GetFamily());
+ }
+ else
+ {
+ // the style does exist
+ pSheet = 0L;
+ }
+ }
+
+ // copy and set the parents
+ pSheet = (SfxStyleSheetBase*)aList.First();
+ SfxStyleSheetBase* pNewSheet = 0L;
+ SfxStyleSheetBase* pLastSheet = 0L;
+ SfxStyleSheetBase* pForThisObject = 0L;
+
+ while(pSheet)
+ {
+ pNewSheet = &pNewPool->Make(pSheet->GetName(), pSheet->GetFamily(), pSheet->GetMask());
+ pNewSheet->GetItemSet().Put(pSheet->GetItemSet(), FALSE);
+
+ if(bScaleUnitChanged)
+ {
+ sdr::properties::ScaleItemSet(pNewSheet->GetItemSet(), aMetricFactor);
+ }
+
+ if(pLastSheet)
+ {
+ pLastSheet->SetParent(pNewSheet->GetName());
+ }
+
+ if(!pForThisObject)
+ {
+ pForThisObject = pNewSheet;
+ }
+
+ pLastSheet = pNewSheet;
+ pSheet = (SfxStyleSheetBase*)aList.Next();
+ }
+
+ // Set link to the Style found in the Pool
+ if(pAnchor && pLastSheet)
+ {
+ pLastSheet->SetParent(pAnchor->GetName());
+ }
+
+ // if list was empty (all Styles exist in destination pool)
+ // pForThisObject is not yet set
+ if(!pForThisObject && pAnchor)
+ {
+ pForThisObject = pAnchor;
+ }
+
+ // De-register at old and register at new Style
+ if(GetStyleSheet() != pForThisObject)
+ {
+ ImpRemoveStyleSheet();
+ ImpAddStyleSheet((SfxStyleSheet*)pForThisObject, sal_True);
+ }
+ }
+ else
+ {
+ // there is no StyleSheetPool in the new model, thus set
+ // all items as hard items in the object
+ List aList;
+ const SfxItemSet* pItemSet = &pOldStyleSheet->GetItemSet();
+
+ while(pItemSet)
+ {
+ aList.Insert((void*)pItemSet, CONTAINER_APPEND);
+ pItemSet = pItemSet->GetParent();
+ }
+
+ SfxItemSet* pNewSet = &CreateObjectSpecificItemSet(pNewModel->GetItemPool());
+ pItemSet = (SfxItemSet*)aList.Last();
+
+ while(pItemSet)
+ {
+ pNewSet->Put(*pItemSet);
+ pItemSet = (SfxItemSet*)aList.Prev();
+ }
+
+ // Items which were hard attributes before need to stay
+ if(mpItemSet)
+ {
+ SfxWhichIter aIter(*mpItemSet);
+ sal_uInt16 nWhich = aIter.FirstWhich();
+
+ while(nWhich)
+ {
+ if(mpItemSet->GetItemState(nWhich, FALSE) == SFX_ITEM_SET)
+ {
+ pNewSet->Put(mpItemSet->Get(nWhich));
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+ }
+
+ if(bScaleUnitChanged)
+ {
+ ScaleItemSet(*pNewSet, aMetricFactor);
+ }
+
+ if(mpItemSet)
+ {
+ if(GetStyleSheet())
+ {
+ ImpRemoveStyleSheet();
+ }
+
+ delete mpItemSet;
+ mpItemSet = 0L;
+ }
+
+ mpItemSet = pNewSet;
+ }
+ }
+ }
+
+ // each object gets the default Style if there is none set yet.
+ if(mpItemSet && !GetStyleSheet() && pNewModel && !pNewModel->IsLoading())
+ {
+ SetStyleSheet(pNewModel->GetDefaultStyleSheet(), sal_True);
+ }
+ }
+ }
+
+ void AttributeProperties::ForceStyleToHardAttributes()
+ {
+ if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
+ {
+ // prepare copied, new itemset, but WITHOUT parent
+ GetObjectItemSet();
+ SfxItemSet* pDestItemSet = new SfxItemSet(*mpItemSet);
+ pDestItemSet->SetParent(0L);
+
+ // pepare forgetting the current stylesheet like in RemoveStyleSheet()
+ EndListening(*mpStyleSheet);
+ EndListening(mpStyleSheet->GetPool());
+
+ // 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;
+
+ // now set all hard attributes of the current at the new itemset
+ while(nWhich)
+ {
+ // #i61284# use mpItemSet with parents, makes things easier and reduces to
+ // one loop
+ if(SFX_ITEM_SET == mpItemSet->GetItemState(nWhich, true, &pItem))
+ {
+ pDestItemSet->Put(*pItem);
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+
+ // replace itemsets
+ delete mpItemSet;
+ mpItemSet = pDestItemSet;
+
+ // set necessary changes like in RemoveStyleSheet()
+ GetSdrObject().SetBoundRectDirty();
+ GetSdrObject().SetRectsDirty(sal_True);
+
+ mpStyleSheet = NULL;
+ }
+ }
+
+ void AttributeProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
+ {
+ sal_Bool bHintUsed(sal_False);
+
+ SfxStyleSheetHint *pStyleHint = PTR_CAST(SfxStyleSheetHint, &rHint);
+
+ if(pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet())
+ {
+ SdrObject& rObj = GetSdrObject();
+ //SdrPage* pPage = rObj.GetPage();
+
+ switch(pStyleHint->GetHint())
+ {
+ case SFX_STYLESHEET_CREATED :
+ {
+ // cannot happen, nothing to do
+ break;
+ }
+ case SFX_STYLESHEET_MODIFIED :
+ case SFX_STYLESHEET_CHANGED :
+ {
+ // notify change
+ break;
+ }
+ case SFX_STYLESHEET_ERASED :
+ case SFX_STYLESHEET_INDESTRUCTION :
+ {
+ // Style needs to be exchanged
+ SfxStyleSheet* pNewStSh = 0L;
+ SdrModel* pModel = rObj.GetModel();
+
+ // #111111#
+ // Do nothing if object is in destruction, else a StyleSheet may be found from
+ // a StyleSheetPool which is just being deleted itself. and thus it would be fatal
+ // to register as listener to that new StyleSheet.
+ if(pModel && !rObj.IsInDestruction())
+ {
+ if(HAS_BASE(SfxStyleSheet, GetStyleSheet()))
+ {
+ pNewStSh = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find(
+ GetStyleSheet()->GetParent(), GetStyleSheet()->GetFamily());
+ }
+
+ if(!pNewStSh)
+ {
+ pNewStSh = pModel->GetDefaultStyleSheet();
+ }
+ }
+
+ // remove used style, it's erased or in destruction
+ ImpRemoveStyleSheet();
+
+ if(pNewStSh)
+ {
+ ImpAddStyleSheet(pNewStSh, sal_True);
+ }
+
+ break;
+ }
+ }
+
+ // Get old BoundRect. Do this after the style change is handled
+ // in the ItemSet parts because GetBoundRect() may calculate a new
+ Rectangle aBoundRect = rObj.GetLastBoundRect();
+
+ rObj.SetRectsDirty(sal_True);
+
+ // tell the object about the change
+ rObj.SetChanged();
+ rObj.BroadcastObjectChange();
+
+ //if(pPage && pPage->IsInserted())
+ //{
+ // rObj.BroadcastObjectChange();
+ //}
+
+ rObj.SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect);
+
+ bHintUsed = sal_True;
+ }
+
+ if(!bHintUsed)
+ {
+ // forward to SdrObject ATM. Not sure if this will be necessary
+ // in the future.
+ GetSdrObject().Notify(rBC, rHint);
+ }
+ }
+ } // end of namespace properties
+} // end of namespace sdr
+
+//////////////////////////////////////////////////////////////////////////////
+// eof