Update ooo320-m1
[ooovba.git] / svx / source / sdr / properties / attributeproperties.cxx
blobc7b82b7c115b059bde59b8256f2f2d82798fa519
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: attributeproperties.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/properties/attributeproperties.hxx>
34 #include <svx/sdr/properties/itemsettools.hxx>
35 #include <tools/debug.hxx>
36 #include <svtools/itemset.hxx>
37 #include <svtools/style.hxx>
38 #include <svtools/whiter.hxx>
39 #include <svtools/poolitem.hxx>
40 #include <svx/svdobj.hxx>
41 #include <svx/svddef.hxx>
42 #include <svx/xit.hxx>
43 #include <svx/xbtmpit.hxx>
44 #include <svx/xlndsit.hxx>
45 #include <svx/xlnstit.hxx>
46 #include <svx/xlnedit.hxx>
47 #include <svx/xflgrit.hxx>
48 #include <svx/xflftrit.hxx>
49 #include <svx/xflhtit.hxx>
50 #include <svx/xlnasit.hxx>
51 #include <svx/xflasit.hxx>
52 #include <svx/svdmodel.hxx>
53 #include <svx/svdtrans.hxx>
54 #include <svx/svdpage.hxx>
56 // #114265#
57 #include <svtools/smplhint.hxx>
59 //////////////////////////////////////////////////////////////////////////////
61 namespace sdr
63 namespace properties
65 void AttributeProperties::ImpAddStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
67 // test if old StyleSheet is cleared, else it would be lost
68 // after this method -> memory leak (!)
69 DBG_ASSERT(!mpStyleSheet, "Old style sheet not deleted before setting new one (!)");
71 if(pNewStyleSheet)
73 mpStyleSheet = pNewStyleSheet;
75 // local ItemSet is needed here, force it
76 GetObjectItemSet();
78 // register as listener
79 StartListening(pNewStyleSheet->GetPool());
80 StartListening(*pNewStyleSheet);
82 // Delete hard attributes where items are set in the style sheet
83 if(!bDontRemoveHardAttr)
85 const SfxItemSet& rStyle = pNewStyleSheet->GetItemSet();
86 SfxWhichIter aIter(rStyle);
87 sal_uInt16 nWhich = aIter.FirstWhich();
89 while(nWhich)
91 if(SFX_ITEM_SET == rStyle.GetItemState(nWhich))
93 mpItemSet->ClearItem(nWhich);
96 nWhich = aIter.NextWhich();
100 // set new stylesheet as parent
101 mpItemSet->SetParent(&pNewStyleSheet->GetItemSet());
105 void AttributeProperties::ImpRemoveStyleSheet()
107 // Check type since it is destroyed when the type is deleted
108 if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
110 EndListening(*mpStyleSheet);
111 EndListening(mpStyleSheet->GetPool());
113 // reset parent of ItemSet
114 if(mpItemSet)
116 mpItemSet->SetParent(0L);
119 SdrObject& rObj = GetSdrObject();
120 rObj.SetBoundRectDirty();
121 rObj.SetRectsDirty(sal_True);
124 mpStyleSheet = 0L;
127 // create a new itemset
128 SfxItemSet& AttributeProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
130 return *(new SfxItemSet(rPool,
132 // ranges from SdrAttrObj
133 SDRATTR_START, SDRATTR_SHADOW_LAST,
134 SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
135 SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
137 // end
138 0, 0));
141 AttributeProperties::AttributeProperties(SdrObject& rObj)
142 : DefaultProperties(rObj),
143 mpStyleSheet(0L)
147 AttributeProperties::AttributeProperties(const AttributeProperties& rProps, SdrObject& rObj)
148 : DefaultProperties(rProps, rObj),
149 mpStyleSheet(0L)
151 if(rProps.GetStyleSheet())
153 ImpAddStyleSheet(rProps.GetStyleSheet(), sal_True);
157 AttributeProperties::~AttributeProperties()
159 ImpRemoveStyleSheet();
162 BaseProperties& AttributeProperties::Clone(SdrObject& rObj) const
164 return *(new AttributeProperties(*this, rObj));
167 void AttributeProperties::ItemSetChanged(const SfxItemSet& /*rSet*/)
169 // own modifications
170 SdrObject& rObj = GetSdrObject();
172 rObj.SetBoundRectDirty();
173 rObj.SetRectsDirty(sal_True);
174 rObj.SetChanged();
177 void AttributeProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
179 if(pNewItem)
181 const SfxPoolItem* pItem = pNewItem;
182 SdrModel* pModel = GetSdrObject().GetModel();
184 switch( nWhich )
186 case XATTR_FILLBITMAP:
188 pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pModel );
189 break;
191 case XATTR_LINEDASH:
193 pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pModel );
194 break;
196 case XATTR_LINESTART:
198 pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pModel );
199 break;
201 case XATTR_LINEEND:
203 pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pModel );
204 break;
206 case XATTR_FILLGRADIENT:
208 pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pModel );
209 break;
211 case XATTR_FILLFLOATTRANSPARENCE:
213 // #85953# allow all kinds of XFillFloatTransparenceItem to be set
214 pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pModel );
215 break;
217 case XATTR_FILLHATCH:
219 pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pModel );
220 break;
224 // set item
225 if(pItem)
227 // force ItemSet
228 GetObjectItemSet();
229 mpItemSet->Put(*pItem);
231 // delete item if it was a generated one
232 if(pItem != pNewItem)
234 delete (SfxPoolItem*)pItem;
238 else
240 // clear item if ItemSet exists
241 if(mpItemSet)
243 mpItemSet->ClearItem(nWhich);
248 void AttributeProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
250 ImpRemoveStyleSheet();
251 ImpAddStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
253 SdrObject& rObj = GetSdrObject();
254 rObj.SetBoundRectDirty();
255 rObj.SetRectsDirty(sal_True);
258 SfxStyleSheet* AttributeProperties::GetStyleSheet() const
260 return mpStyleSheet;
263 void AttributeProperties::MoveToItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel)
265 if(pSrcPool && pDestPool && (pSrcPool != pDestPool))
267 if(mpItemSet)
269 // migrate ItemSet to new pool. Scaling is NOT necessary
270 // because this functionality is used by UNDO only. Thus
271 // objects and ItemSets would be moved back to their original
272 // pool before usage.
273 SfxItemSet* pOldSet = mpItemSet;
274 SfxStyleSheet* pStySheet = GetStyleSheet();
276 if(pStySheet)
278 ImpRemoveStyleSheet();
281 mpItemSet = mpItemSet->Clone(FALSE, pDestPool);
282 GetSdrObject().GetModel()->MigrateItemSet(pOldSet, mpItemSet, pNewModel);
284 // set stylesheet (if used)
285 if(pStySheet)
287 ImpAddStyleSheet(pStySheet, sal_True);
290 delete pOldSet;
295 void AttributeProperties::SetModel(SdrModel* pOldModel, SdrModel* pNewModel)
297 if(pOldModel != pNewModel && pNewModel && !pNewModel->IsLoading())
299 // For a living model move the items from one pool to the other
300 if(pOldModel)
302 // If metric has changed, scale items.
303 MapUnit aOldUnit(pOldModel->GetScaleUnit());
304 MapUnit aNewUnit(pNewModel->GetScaleUnit());
305 sal_Bool bScaleUnitChanged(aNewUnit != aOldUnit);
306 Fraction aMetricFactor;
308 if(bScaleUnitChanged)
310 aMetricFactor = GetMapFactor(aOldUnit, aNewUnit).X();
311 Scale(aMetricFactor);
314 // Move all styles which are used by the object to the new
315 // StyleSheet pool
316 SfxStyleSheet* pOldStyleSheet = GetStyleSheet();
318 if(pOldStyleSheet)
320 SfxStyleSheetBase* pSheet = pOldStyleSheet;
321 SfxStyleSheetBasePool* pOldPool = pOldModel->GetStyleSheetPool();
322 SfxStyleSheetBasePool* pNewPool = pNewModel->GetStyleSheetPool();
323 DBG_ASSERT(pOldPool, "Properties::SetModel(): Object has StyleSheet but no StyleSheetPool (!)");
325 if(pOldPool && pNewPool)
327 // build a list of to-be-copied Styles
328 List aList;
329 SfxStyleSheetBase* pAnchor = 0L;
331 while(pSheet)
333 pAnchor = pNewPool->Find(pSheet->GetName(), pSheet->GetFamily());
335 if(!pAnchor)
337 aList.Insert(pSheet, LIST_APPEND);
338 pSheet = pOldPool->Find(pSheet->GetParent(), pSheet->GetFamily());
340 else
342 // the style does exist
343 pSheet = 0L;
347 // copy and set the parents
348 pSheet = (SfxStyleSheetBase*)aList.First();
349 SfxStyleSheetBase* pNewSheet = 0L;
350 SfxStyleSheetBase* pLastSheet = 0L;
351 SfxStyleSheetBase* pForThisObject = 0L;
353 while(pSheet)
355 pNewSheet = &pNewPool->Make(pSheet->GetName(), pSheet->GetFamily(), pSheet->GetMask());
356 pNewSheet->GetItemSet().Put(pSheet->GetItemSet(), FALSE);
358 if(bScaleUnitChanged)
360 sdr::properties::ScaleItemSet(pNewSheet->GetItemSet(), aMetricFactor);
363 if(pLastSheet)
365 pLastSheet->SetParent(pNewSheet->GetName());
368 if(!pForThisObject)
370 pForThisObject = pNewSheet;
373 pLastSheet = pNewSheet;
374 pSheet = (SfxStyleSheetBase*)aList.Next();
377 // Set link to the Style found in the Pool
378 if(pAnchor && pLastSheet)
380 pLastSheet->SetParent(pAnchor->GetName());
383 // if list was empty (all Styles exist in destination pool)
384 // pForThisObject is not yet set
385 if(!pForThisObject && pAnchor)
387 pForThisObject = pAnchor;
390 // De-register at old and register at new Style
391 if(GetStyleSheet() != pForThisObject)
393 ImpRemoveStyleSheet();
394 ImpAddStyleSheet((SfxStyleSheet*)pForThisObject, sal_True);
397 else
399 // there is no StyleSheetPool in the new model, thus set
400 // all items as hard items in the object
401 List aList;
402 const SfxItemSet* pItemSet = &pOldStyleSheet->GetItemSet();
404 while(pItemSet)
406 aList.Insert((void*)pItemSet, CONTAINER_APPEND);
407 pItemSet = pItemSet->GetParent();
410 SfxItemSet* pNewSet = &CreateObjectSpecificItemSet(pNewModel->GetItemPool());
411 pItemSet = (SfxItemSet*)aList.Last();
413 while(pItemSet)
415 pNewSet->Put(*pItemSet);
416 pItemSet = (SfxItemSet*)aList.Prev();
419 // Items which were hard attributes before need to stay
420 if(mpItemSet)
422 SfxWhichIter aIter(*mpItemSet);
423 sal_uInt16 nWhich = aIter.FirstWhich();
425 while(nWhich)
427 if(mpItemSet->GetItemState(nWhich, FALSE) == SFX_ITEM_SET)
429 pNewSet->Put(mpItemSet->Get(nWhich));
432 nWhich = aIter.NextWhich();
436 if(bScaleUnitChanged)
438 ScaleItemSet(*pNewSet, aMetricFactor);
441 if(mpItemSet)
443 if(GetStyleSheet())
445 ImpRemoveStyleSheet();
448 delete mpItemSet;
449 mpItemSet = 0L;
452 mpItemSet = pNewSet;
457 // each object gets the default Style if there is none set yet.
458 if(mpItemSet && !GetStyleSheet() && pNewModel && !pNewModel->IsLoading())
460 SetStyleSheet(pNewModel->GetDefaultStyleSheet(), sal_True);
465 void AttributeProperties::ForceStyleToHardAttributes()
467 if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
469 // prepare copied, new itemset, but WITHOUT parent
470 GetObjectItemSet();
471 SfxItemSet* pDestItemSet = new SfxItemSet(*mpItemSet);
472 pDestItemSet->SetParent(0L);
474 // pepare forgetting the current stylesheet like in RemoveStyleSheet()
475 EndListening(*mpStyleSheet);
476 EndListening(mpStyleSheet->GetPool());
478 // prepare the iter; use the mpObjectItemSet which may have less
479 // WhichIDs than the style.
480 SfxWhichIter aIter(*pDestItemSet);
481 sal_uInt16 nWhich(aIter.FirstWhich());
482 const SfxPoolItem *pItem = NULL;
484 // now set all hard attributes of the current at the new itemset
485 while(nWhich)
487 // #i61284# use mpItemSet with parents, makes things easier and reduces to
488 // one loop
489 if(SFX_ITEM_SET == mpItemSet->GetItemState(nWhich, true, &pItem))
491 pDestItemSet->Put(*pItem);
494 nWhich = aIter.NextWhich();
497 // replace itemsets
498 delete mpItemSet;
499 mpItemSet = pDestItemSet;
501 // set necessary changes like in RemoveStyleSheet()
502 GetSdrObject().SetBoundRectDirty();
503 GetSdrObject().SetRectsDirty(sal_True);
505 mpStyleSheet = NULL;
509 void AttributeProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
511 sal_Bool bHintUsed(sal_False);
513 SfxStyleSheetHint *pStyleHint = PTR_CAST(SfxStyleSheetHint, &rHint);
515 if(pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet())
517 SdrObject& rObj = GetSdrObject();
518 //SdrPage* pPage = rObj.GetPage();
520 switch(pStyleHint->GetHint())
522 case SFX_STYLESHEET_CREATED :
524 // cannot happen, nothing to do
525 break;
527 case SFX_STYLESHEET_MODIFIED :
528 case SFX_STYLESHEET_CHANGED :
530 // notify change
531 break;
533 case SFX_STYLESHEET_ERASED :
534 case SFX_STYLESHEET_INDESTRUCTION :
536 // Style needs to be exchanged
537 SfxStyleSheet* pNewStSh = 0L;
538 SdrModel* pModel = rObj.GetModel();
540 // #111111#
541 // Do nothing if object is in destruction, else a StyleSheet may be found from
542 // a StyleSheetPool which is just being deleted itself. and thus it would be fatal
543 // to register as listener to that new StyleSheet.
544 if(pModel && !rObj.IsInDestruction())
546 if(HAS_BASE(SfxStyleSheet, GetStyleSheet()))
548 pNewStSh = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find(
549 GetStyleSheet()->GetParent(), GetStyleSheet()->GetFamily());
552 if(!pNewStSh)
554 pNewStSh = pModel->GetDefaultStyleSheet();
558 // remove used style, it's erased or in destruction
559 ImpRemoveStyleSheet();
561 if(pNewStSh)
563 ImpAddStyleSheet(pNewStSh, sal_True);
566 break;
570 // Get old BoundRect. Do this after the style change is handled
571 // in the ItemSet parts because GetBoundRect() may calculate a new
572 Rectangle aBoundRect = rObj.GetLastBoundRect();
574 rObj.SetRectsDirty(sal_True);
576 // tell the object about the change
577 rObj.SetChanged();
578 rObj.BroadcastObjectChange();
580 //if(pPage && pPage->IsInserted())
582 // rObj.BroadcastObjectChange();
585 rObj.SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect);
587 bHintUsed = sal_True;
590 // #111111#
591 // When it's the BackgroundObject, set the MasterPage to changed to
592 // get a refresh for the evtl. changed BackgroundStyle
594 // #114265#
595 // To only invalidate the page when the StyleSheet change happens,
596 // some more rigid testing is necessary.
597 const SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
599 if(pSimpleHint
600 && pSimpleHint->GetId() == SFX_HINT_DATACHANGED
601 && GetSdrObject().IsMasterPageBackgroundObject())
603 GetSdrObject().GetPage()->ActionChanged();
606 if(!bHintUsed)
608 // forward to SdrObject ATM. Not sure if this will be necessary
609 // in the future.
610 GetSdrObject().Notify(rBC, rHint);
613 } // end of namespace properties
614 } // end of namespace sdr
616 //////////////////////////////////////////////////////////////////////////////
617 // eof