1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
44 #include <svl/smplhint.hxx>
46 //////////////////////////////////////////////////////////////////////////////
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 (!)");
60 mpStyleSheet
= pNewStyleSheet
;
62 // local ItemSet is needed here, force it
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();
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
103 mpItemSet
->SetParent(0L);
106 SdrObject
& rObj
= GetSdrObject();
107 rObj
.SetBoundRectDirty();
108 rObj
.SetRectsDirty(sal_True
);
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
,
128 AttributeProperties::AttributeProperties(SdrObject
& rObj
)
129 : DefaultProperties(rObj
),
134 AttributeProperties::AttributeProperties(const AttributeProperties
& rProps
, SdrObject
& rObj
)
135 : DefaultProperties(rProps
, rObj
),
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*/)
157 SdrObject
& rObj
= GetSdrObject();
159 rObj
.SetBoundRectDirty();
160 rObj
.SetRectsDirty(sal_True
);
164 void AttributeProperties::ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
)
168 const SfxPoolItem
* pItem
= pNewItem
;
169 SdrModel
* pModel
= GetSdrObject().GetModel();
173 case XATTR_FILLBITMAP
:
175 pItem
= ((XFillBitmapItem
*)pItem
)->checkForUniqueItem( pModel
);
180 pItem
= ((XLineDashItem
*)pItem
)->checkForUniqueItem( pModel
);
183 case XATTR_LINESTART
:
185 pItem
= ((XLineStartItem
*)pItem
)->checkForUniqueItem( pModel
);
190 pItem
= ((XLineEndItem
*)pItem
)->checkForUniqueItem( pModel
);
193 case XATTR_FILLGRADIENT
:
195 pItem
= ((XFillGradientItem
*)pItem
)->checkForUniqueItem( pModel
);
198 case XATTR_FILLFLOATTRANSPARENCE
:
200 // #85953# allow all kinds of XFillFloatTransparenceItem to be set
201 pItem
= ((XFillFloatTransparenceItem
*)pItem
)->checkForUniqueItem( pModel
);
204 case XATTR_FILLHATCH
:
206 pItem
= ((XFillHatchItem
*)pItem
)->checkForUniqueItem( pModel
);
216 mpItemSet
->Put(*pItem
);
218 // delete item if it was a generated one
219 if(pItem
!= pNewItem
)
221 delete (SfxPoolItem
*)pItem
;
227 // clear item if ItemSet exists
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
250 void AttributeProperties::MoveToItemPool(SfxItemPool
* pSrcPool
, SfxItemPool
* pDestPool
, SdrModel
* pNewModel
)
252 OSL_ASSERT(pNewModel
!=NULL
);
254 if(pSrcPool
&& pDestPool
&& (pSrcPool
!= pDestPool
))
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();
267 ImpRemoveStyleSheet();
270 mpItemSet
= mpItemSet
->Clone(sal_False
, pDestPool
);
271 GetSdrObject().GetModel()->MigrateItemSet(pOldSet
, mpItemSet
, pNewModel
);
273 // set stylesheet (if used)
277 SfxItemPool
* pStyleSheetPool
= &pStySheet
->GetPool().GetPool();
279 if(pStyleSheetPool
== pDestPool
)
281 // just re-set stylesheet
282 ImpAddStyleSheet(pStySheet
, sal_True
);
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
);
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
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
333 SfxStyleSheet
* pOldStyleSheet
= GetStyleSheet();
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;
350 pAnchor
= pNewPool
->Find(pSheet
->GetName(), pSheet
->GetFamily());
354 aStyleList
.push_back(pSheet
);
355 pSheet
= pOldPool
->Find(pSheet
->GetParent(), pSheet
->GetFamily());
359 // the style does exist
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
);
382 pLastSheet
->SetParent(pNewSheet
->GetName());
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
);
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();
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
435 SfxWhichIter
aIter(*mpItemSet
);
436 sal_uInt16 nWhich
= aIter
.FirstWhich();
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
);
458 ImpRemoveStyleSheet();
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
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
501 // #i61284# use mpItemSet with parents, makes things easier and reduces to
503 if(SFX_ITEM_SET
== mpItemSet
->GetItemState(nWhich
, true, &pItem
))
505 pDestItemSet
->Put(*pItem
);
508 nWhich
= aIter
.NextWhich();
513 mpItemSet
= pDestItemSet
;
515 // set necessary changes like in RemoveStyleSheet()
516 GetSdrObject().SetBoundRectDirty();
517 GetSdrObject().SetRectsDirty(sal_True
);
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
541 case SFX_STYLESHEET_MODIFIED
:
542 case SFX_STYLESHEET_CHANGED
:
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();
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());
568 pNewStSh
= pModel
->GetDefaultStyleSheet();
572 // remove used style, it's erased or in destruction
573 ImpRemoveStyleSheet();
577 ImpAddStyleSheet(pNewStSh
, sal_True
);
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
592 rObj
.BroadcastObjectChange();
594 //if(pPage && pPage->IsInserted())
596 // rObj.BroadcastObjectChange();
599 rObj
.SendUserCall(SDRUSERCALL_CHGATTR
, aBoundRect
);
601 bHintUsed
= sal_True
;
606 // forward to SdrObject ATM. Not sure if this will be necessary
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())
623 } // end of namespace properties
624 } // end of namespace sdr
626 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */