bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / sdr / properties / attributeproperties.cxx
blob54386de0e0b88c4d17cac8a657b3c9e42cc1c892
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/sdr/properties/attributeproperties.hxx>
21 #include <svx/sdr/properties/itemsettools.hxx>
22 #include <tools/debug.hxx>
23 #include <svl/itemset.hxx>
24 #include <svl/style.hxx>
25 #include <svl/whiter.hxx>
26 #include <svl/poolitem.hxx>
27 #include <svx/svdobj.hxx>
28 #include <svx/svddef.hxx>
29 #include <svx/xit.hxx>
30 #include <svx/xbtmpit.hxx>
31 #include <svx/xlndsit.hxx>
32 #include <svx/xlnstit.hxx>
33 #include <svx/xlnedit.hxx>
34 #include <svx/xflgrit.hxx>
35 #include <svx/xflftrit.hxx>
36 #include <svx/xflhtit.hxx>
37 #include <svx/xlnasit.hxx>
38 #include <svx/xflasit.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/svdtrans.hxx>
41 #include <svx/svdpage.hxx>
43 // #114265#
44 #include <svl/smplhint.hxx>
46 //////////////////////////////////////////////////////////////////////////////
48 namespace sdr
50 namespace properties
52 void AttributeProperties::ImpAddStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
54 // test if old StyleSheet is cleared, else it would be lost
55 // after this method -> memory leak (!)
56 DBG_ASSERT(!mpStyleSheet, "Old style sheet not deleted before setting new one (!)");
58 if(pNewStyleSheet)
60 mpStyleSheet = pNewStyleSheet;
62 // local ItemSet is needed here, force it
63 GetObjectItemSet();
65 // register as listener
66 StartListening(pNewStyleSheet->GetPool());
67 StartListening(*pNewStyleSheet);
69 // Delete hard attributes where items are set in the style sheet
70 if(!bDontRemoveHardAttr)
72 const SfxItemSet& rStyle = pNewStyleSheet->GetItemSet();
73 SfxWhichIter aIter(rStyle);
74 sal_uInt16 nWhich = aIter.FirstWhich();
76 while(nWhich)
78 if(SFX_ITEM_SET == rStyle.GetItemState(nWhich))
80 mpItemSet->ClearItem(nWhich);
83 nWhich = aIter.NextWhich();
87 // set new stylesheet as parent
88 mpItemSet->SetParent(&pNewStyleSheet->GetItemSet());
92 void AttributeProperties::ImpRemoveStyleSheet()
94 // Check type since it is destroyed when the type is deleted
95 if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
97 EndListening(*mpStyleSheet);
98 EndListening(mpStyleSheet->GetPool());
100 // reset parent of ItemSet
101 if(mpItemSet)
103 mpItemSet->SetParent(0L);
106 SdrObject& rObj = GetSdrObject();
107 rObj.SetBoundRectDirty();
108 rObj.SetRectsDirty(sal_True);
111 mpStyleSheet = 0L;
114 // create a new itemset
115 SfxItemSet& AttributeProperties::CreateObjectSpecificItemSet(SfxItemPool& rPool)
117 return *(new SfxItemSet(rPool,
119 // ranges from SdrAttrObj
120 SDRATTR_START, SDRATTR_SHADOW_LAST,
121 SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST,
122 SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION,
124 // end
125 0, 0));
128 AttributeProperties::AttributeProperties(SdrObject& rObj)
129 : DefaultProperties(rObj),
130 mpStyleSheet(0L)
134 AttributeProperties::AttributeProperties(const AttributeProperties& rProps, SdrObject& rObj)
135 : DefaultProperties(rProps, rObj),
136 mpStyleSheet(0L)
138 if(rProps.GetStyleSheet())
140 ImpAddStyleSheet(rProps.GetStyleSheet(), sal_True);
144 AttributeProperties::~AttributeProperties()
146 ImpRemoveStyleSheet();
149 BaseProperties& AttributeProperties::Clone(SdrObject& rObj) const
151 return *(new AttributeProperties(*this, rObj));
154 void AttributeProperties::ItemSetChanged(const SfxItemSet& /*rSet*/)
156 // own modifications
157 SdrObject& rObj = GetSdrObject();
159 rObj.SetBoundRectDirty();
160 rObj.SetRectsDirty(sal_True);
161 rObj.SetChanged();
164 void AttributeProperties::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
166 if(pNewItem)
168 const SfxPoolItem* pItem = pNewItem;
169 SdrModel* pModel = GetSdrObject().GetModel();
171 switch( nWhich )
173 case XATTR_FILLBITMAP:
175 pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pModel );
176 break;
178 case XATTR_LINEDASH:
180 pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pModel );
181 break;
183 case XATTR_LINESTART:
185 pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pModel );
186 break;
188 case XATTR_LINEEND:
190 pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pModel );
191 break;
193 case XATTR_FILLGRADIENT:
195 pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pModel );
196 break;
198 case XATTR_FILLFLOATTRANSPARENCE:
200 // #85953# allow all kinds of XFillFloatTransparenceItem to be set
201 pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pModel );
202 break;
204 case XATTR_FILLHATCH:
206 pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pModel );
207 break;
211 // set item
212 if(pItem)
214 // force ItemSet
215 GetObjectItemSet();
216 mpItemSet->Put(*pItem);
218 // delete item if it was a generated one
219 if(pItem != pNewItem)
221 delete (SfxPoolItem*)pItem;
225 else
227 // clear item if ItemSet exists
228 if(mpItemSet)
230 mpItemSet->ClearItem(nWhich);
235 void AttributeProperties::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, sal_Bool bDontRemoveHardAttr)
237 ImpRemoveStyleSheet();
238 ImpAddStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
240 SdrObject& rObj = GetSdrObject();
241 rObj.SetBoundRectDirty();
242 rObj.SetRectsDirty(sal_True);
245 SfxStyleSheet* AttributeProperties::GetStyleSheet() const
247 return mpStyleSheet;
250 void AttributeProperties::MoveToItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool, SdrModel* pNewModel)
252 OSL_ASSERT(pNewModel!=NULL);
254 if(pSrcPool && pDestPool && (pSrcPool != pDestPool))
256 if(mpItemSet)
258 // migrate ItemSet to new pool. Scaling is NOT necessary
259 // because this functionality is used by UNDO only. Thus
260 // objects and ItemSets would be moved back to their original
261 // pool before usage.
262 SfxItemSet* pOldSet = mpItemSet;
263 SfxStyleSheet* pStySheet = GetStyleSheet();
265 if(pStySheet)
267 ImpRemoveStyleSheet();
270 mpItemSet = mpItemSet->Clone(sal_False, pDestPool);
271 GetSdrObject().GetModel()->MigrateItemSet(pOldSet, mpItemSet, pNewModel);
273 // set stylesheet (if used)
274 if(pStySheet)
276 // #i109515#
277 SfxItemPool* pStyleSheetPool = &pStySheet->GetPool().GetPool();
279 if(pStyleSheetPool == pDestPool)
281 // just re-set stylesheet
282 ImpAddStyleSheet(pStySheet, sal_True);
284 else
286 // StyleSheet is NOT from the correct pool.
287 // Look one up in the right pool with the same
288 // name or use the default.
290 // Look up the style in the new document.
291 OSL_ASSERT(pNewModel->GetStyleSheetPool() != NULL);
292 SfxStyleSheet* pNewStyleSheet = dynamic_cast<SfxStyleSheet*>(
293 pNewModel->GetStyleSheetPool()->Find(
294 pStySheet->GetName(),
295 SFX_STYLE_FAMILY_ALL));
296 if (pNewStyleSheet == NULL
297 || &pNewStyleSheet->GetPool().GetPool() != pDestPool)
299 // There is no copy of the style in the new
300 // document. Use the default as a fallback.
301 pNewStyleSheet = pNewModel->GetDefaultStyleSheet();
303 ImpAddStyleSheet(pNewStyleSheet, sal_True);
307 delete pOldSet;
312 void AttributeProperties::SetModel(SdrModel* pOldModel, SdrModel* pNewModel)
314 if(pOldModel != pNewModel && pNewModel && !pNewModel->IsLoading())
316 // For a living model move the items from one pool to the other
317 if(pOldModel)
319 // If metric has changed, scale items.
320 MapUnit aOldUnit(pOldModel->GetScaleUnit());
321 MapUnit aNewUnit(pNewModel->GetScaleUnit());
322 sal_Bool bScaleUnitChanged(aNewUnit != aOldUnit);
323 Fraction aMetricFactor;
325 if(bScaleUnitChanged)
327 aMetricFactor = GetMapFactor(aOldUnit, aNewUnit).X();
328 Scale(aMetricFactor);
331 // Move all styles which are used by the object to the new
332 // StyleSheet pool
333 SfxStyleSheet* pOldStyleSheet = GetStyleSheet();
335 if(pOldStyleSheet)
337 SfxStyleSheetBase* pSheet = pOldStyleSheet;
338 SfxStyleSheetBasePool* pOldPool = pOldModel->GetStyleSheetPool();
339 SfxStyleSheetBasePool* pNewPool = pNewModel->GetStyleSheetPool();
340 DBG_ASSERT(pOldPool, "Properties::SetModel(): Object has StyleSheet but no StyleSheetPool (!)");
342 if(pOldPool && pNewPool)
344 // build a list of to-be-copied Styles
345 std::vector<SfxStyleSheetBase*> aStyleList;
346 SfxStyleSheetBase* pAnchor = 0L;
348 while(pSheet)
350 pAnchor = pNewPool->Find(pSheet->GetName(), pSheet->GetFamily());
352 if(!pAnchor)
354 aStyleList.push_back(pSheet);
355 pSheet = pOldPool->Find(pSheet->GetParent(), pSheet->GetFamily());
357 else
359 // the style does exist
360 pSheet = 0L;
364 // copy and set the parents
365 SfxStyleSheetBase* pNewSheet = 0L;
366 SfxStyleSheetBase* pLastSheet = 0L;
367 SfxStyleSheetBase* pForThisObject = 0L;
369 std::vector<SfxStyleSheetBase*>::iterator iter;
370 for (iter = aStyleList.begin(); iter != aStyleList.end(); ++iter)
372 pNewSheet = &pNewPool->Make((*iter)->GetName(), (*iter)->GetFamily(), (*iter)->GetMask());
373 pNewSheet->GetItemSet().Put((*iter)->GetItemSet(), sal_False);
375 if(bScaleUnitChanged)
377 sdr::properties::ScaleItemSet(pNewSheet->GetItemSet(), aMetricFactor);
380 if(pLastSheet)
382 pLastSheet->SetParent(pNewSheet->GetName());
385 if(!pForThisObject)
387 pForThisObject = pNewSheet;
390 pLastSheet = pNewSheet;
393 // Set link to the Style found in the Pool
394 if(pAnchor && pLastSheet)
396 pLastSheet->SetParent(pAnchor->GetName());
399 // if list was empty (all Styles exist in destination pool)
400 // pForThisObject is not yet set
401 if(!pForThisObject && pAnchor)
403 pForThisObject = pAnchor;
406 // De-register at old and register at new Style
407 if(GetStyleSheet() != pForThisObject)
409 ImpRemoveStyleSheet();
410 ImpAddStyleSheet((SfxStyleSheet*)pForThisObject, sal_True);
413 else
415 // there is no StyleSheetPool in the new model, thus set
416 // all items as hard items in the object
417 std::vector<const SfxItemSet*> aSetList;
418 const SfxItemSet* pItemSet = &pOldStyleSheet->GetItemSet();
420 while(pItemSet)
422 aSetList.push_back(pItemSet);
423 pItemSet = pItemSet->GetParent();
426 SfxItemSet* pNewSet = &CreateObjectSpecificItemSet(pNewModel->GetItemPool());
428 std::vector<const SfxItemSet*>::reverse_iterator riter;
429 for (riter = aSetList.rbegin(); riter != aSetList.rend(); ++riter)
430 pNewSet->Put(*(*riter));
432 // Items which were hard attributes before need to stay
433 if(mpItemSet)
435 SfxWhichIter aIter(*mpItemSet);
436 sal_uInt16 nWhich = aIter.FirstWhich();
438 while(nWhich)
440 if(mpItemSet->GetItemState(nWhich, sal_False) == SFX_ITEM_SET)
442 pNewSet->Put(mpItemSet->Get(nWhich));
445 nWhich = aIter.NextWhich();
449 if(bScaleUnitChanged)
451 ScaleItemSet(*pNewSet, aMetricFactor);
454 if(mpItemSet)
456 if(GetStyleSheet())
458 ImpRemoveStyleSheet();
461 delete mpItemSet;
462 mpItemSet = 0L;
465 mpItemSet = pNewSet;
470 // each object gets the default Style if there is none set yet.
471 if(!GetStyleSheet() && pNewModel && !pNewModel->IsLoading())
473 GetObjectItemSet(); // #118414 force ItemSet to allow style to be set
474 SetStyleSheet(pNewModel->GetDefaultStyleSheet(), sal_True);
479 void AttributeProperties::ForceStyleToHardAttributes()
481 if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
483 // prepare copied, new itemset, but WITHOUT parent
484 GetObjectItemSet();
485 SfxItemSet* pDestItemSet = new SfxItemSet(*mpItemSet);
486 pDestItemSet->SetParent(0L);
488 // pepare forgetting the current stylesheet like in RemoveStyleSheet()
489 EndListening(*mpStyleSheet);
490 EndListening(mpStyleSheet->GetPool());
492 // prepare the iter; use the mpObjectItemSet which may have less
493 // WhichIDs than the style.
494 SfxWhichIter aIter(*pDestItemSet);
495 sal_uInt16 nWhich(aIter.FirstWhich());
496 const SfxPoolItem *pItem = NULL;
498 // now set all hard attributes of the current at the new itemset
499 while(nWhich)
501 // #i61284# use mpItemSet with parents, makes things easier and reduces to
502 // one loop
503 if(SFX_ITEM_SET == mpItemSet->GetItemState(nWhich, true, &pItem))
505 pDestItemSet->Put(*pItem);
508 nWhich = aIter.NextWhich();
511 // replace itemsets
512 delete mpItemSet;
513 mpItemSet = pDestItemSet;
515 // set necessary changes like in RemoveStyleSheet()
516 GetSdrObject().SetBoundRectDirty();
517 GetSdrObject().SetRectsDirty(sal_True);
519 mpStyleSheet = NULL;
523 void AttributeProperties::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
525 sal_Bool bHintUsed(sal_False);
527 SfxStyleSheetHint *pStyleHint = PTR_CAST(SfxStyleSheetHint, &rHint);
529 if(pStyleHint && pStyleHint->GetStyleSheet() == GetStyleSheet())
531 SdrObject& rObj = GetSdrObject();
532 //SdrPage* pPage = rObj.GetPage();
534 switch(pStyleHint->GetHint())
536 case SFX_STYLESHEET_CREATED :
538 // cannot happen, nothing to do
539 break;
541 case SFX_STYLESHEET_MODIFIED :
542 case SFX_STYLESHEET_CHANGED :
544 // notify change
545 break;
547 case SFX_STYLESHEET_ERASED :
548 case SFX_STYLESHEET_INDESTRUCTION :
550 // Style needs to be exchanged
551 SfxStyleSheet* pNewStSh = 0L;
552 SdrModel* pModel = rObj.GetModel();
554 // #111111#
555 // Do nothing if object is in destruction, else a StyleSheet may be found from
556 // a StyleSheetPool which is just being deleted itself. and thus it would be fatal
557 // to register as listener to that new StyleSheet.
558 if(pModel && !rObj.IsInDestruction())
560 if(HAS_BASE(SfxStyleSheet, GetStyleSheet()))
562 pNewStSh = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find(
563 GetStyleSheet()->GetParent(), GetStyleSheet()->GetFamily());
566 if(!pNewStSh)
568 pNewStSh = pModel->GetDefaultStyleSheet();
572 // remove used style, it's erased or in destruction
573 ImpRemoveStyleSheet();
575 if(pNewStSh)
577 ImpAddStyleSheet(pNewStSh, sal_True);
580 break;
584 // Get old BoundRect. Do this after the style change is handled
585 // in the ItemSet parts because GetBoundRect() may calculate a new
586 Rectangle aBoundRect = rObj.GetLastBoundRect();
588 rObj.SetRectsDirty(sal_True);
590 // tell the object about the change
591 rObj.SetChanged();
592 rObj.BroadcastObjectChange();
594 //if(pPage && pPage->IsInserted())
596 // rObj.BroadcastObjectChange();
599 rObj.SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect);
601 bHintUsed = sal_True;
604 if(!bHintUsed)
606 // forward to SdrObject ATM. Not sure if this will be necessary
607 // in the future.
608 GetSdrObject().Notify(rBC, rHint);
612 bool AttributeProperties::isUsedByModel() const
614 const SdrObject& rObj(GetSdrObject());
615 if (rObj.IsInserted())
617 const SdrPage* const pPage(rObj.GetPage());
618 if (pPage && pPage->IsInserted())
619 return true;
621 return false;
623 } // end of namespace properties
624 } // end of namespace sdr
626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */