1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: attributeproperties.cxx,v $
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>
57 #include <svtools/smplhint.hxx>
59 //////////////////////////////////////////////////////////////////////////////
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 (!)");
73 mpStyleSheet
= pNewStyleSheet
;
75 // local ItemSet is needed here, force it
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();
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
116 mpItemSet
->SetParent(0L);
119 SdrObject
& rObj
= GetSdrObject();
120 rObj
.SetBoundRectDirty();
121 rObj
.SetRectsDirty(sal_True
);
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
,
141 AttributeProperties::AttributeProperties(SdrObject
& rObj
)
142 : DefaultProperties(rObj
),
147 AttributeProperties::AttributeProperties(const AttributeProperties
& rProps
, SdrObject
& rObj
)
148 : DefaultProperties(rProps
, rObj
),
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*/)
170 SdrObject
& rObj
= GetSdrObject();
172 rObj
.SetBoundRectDirty();
173 rObj
.SetRectsDirty(sal_True
);
177 void AttributeProperties::ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
)
181 const SfxPoolItem
* pItem
= pNewItem
;
182 SdrModel
* pModel
= GetSdrObject().GetModel();
186 case XATTR_FILLBITMAP
:
188 pItem
= ((XFillBitmapItem
*)pItem
)->checkForUniqueItem( pModel
);
193 pItem
= ((XLineDashItem
*)pItem
)->checkForUniqueItem( pModel
);
196 case XATTR_LINESTART
:
198 pItem
= ((XLineStartItem
*)pItem
)->checkForUniqueItem( pModel
);
203 pItem
= ((XLineEndItem
*)pItem
)->checkForUniqueItem( pModel
);
206 case XATTR_FILLGRADIENT
:
208 pItem
= ((XFillGradientItem
*)pItem
)->checkForUniqueItem( pModel
);
211 case XATTR_FILLFLOATTRANSPARENCE
:
213 // #85953# allow all kinds of XFillFloatTransparenceItem to be set
214 pItem
= ((XFillFloatTransparenceItem
*)pItem
)->checkForUniqueItem( pModel
);
217 case XATTR_FILLHATCH
:
219 pItem
= ((XFillHatchItem
*)pItem
)->checkForUniqueItem( pModel
);
229 mpItemSet
->Put(*pItem
);
231 // delete item if it was a generated one
232 if(pItem
!= pNewItem
)
234 delete (SfxPoolItem
*)pItem
;
240 // clear item if ItemSet exists
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
263 void AttributeProperties::MoveToItemPool(SfxItemPool
* pSrcPool
, SfxItemPool
* pDestPool
, SdrModel
* pNewModel
)
265 if(pSrcPool
&& pDestPool
&& (pSrcPool
!= pDestPool
))
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();
278 ImpRemoveStyleSheet();
281 mpItemSet
= mpItemSet
->Clone(FALSE
, pDestPool
);
282 GetSdrObject().GetModel()->MigrateItemSet(pOldSet
, mpItemSet
, pNewModel
);
284 // set stylesheet (if used)
287 ImpAddStyleSheet(pStySheet
, sal_True
);
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
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
316 SfxStyleSheet
* pOldStyleSheet
= GetStyleSheet();
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
329 SfxStyleSheetBase
* pAnchor
= 0L;
333 pAnchor
= pNewPool
->Find(pSheet
->GetName(), pSheet
->GetFamily());
337 aList
.Insert(pSheet
, LIST_APPEND
);
338 pSheet
= pOldPool
->Find(pSheet
->GetParent(), pSheet
->GetFamily());
342 // the style does exist
347 // copy and set the parents
348 pSheet
= (SfxStyleSheetBase
*)aList
.First();
349 SfxStyleSheetBase
* pNewSheet
= 0L;
350 SfxStyleSheetBase
* pLastSheet
= 0L;
351 SfxStyleSheetBase
* pForThisObject
= 0L;
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
);
365 pLastSheet
->SetParent(pNewSheet
->GetName());
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
);
399 // there is no StyleSheetPool in the new model, thus set
400 // all items as hard items in the object
402 const SfxItemSet
* pItemSet
= &pOldStyleSheet
->GetItemSet();
406 aList
.Insert((void*)pItemSet
, CONTAINER_APPEND
);
407 pItemSet
= pItemSet
->GetParent();
410 SfxItemSet
* pNewSet
= &CreateObjectSpecificItemSet(pNewModel
->GetItemPool());
411 pItemSet
= (SfxItemSet
*)aList
.Last();
415 pNewSet
->Put(*pItemSet
);
416 pItemSet
= (SfxItemSet
*)aList
.Prev();
419 // Items which were hard attributes before need to stay
422 SfxWhichIter
aIter(*mpItemSet
);
423 sal_uInt16 nWhich
= aIter
.FirstWhich();
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
);
445 ImpRemoveStyleSheet();
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
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
487 // #i61284# use mpItemSet with parents, makes things easier and reduces to
489 if(SFX_ITEM_SET
== mpItemSet
->GetItemState(nWhich
, true, &pItem
))
491 pDestItemSet
->Put(*pItem
);
494 nWhich
= aIter
.NextWhich();
499 mpItemSet
= pDestItemSet
;
501 // set necessary changes like in RemoveStyleSheet()
502 GetSdrObject().SetBoundRectDirty();
503 GetSdrObject().SetRectsDirty(sal_True
);
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
527 case SFX_STYLESHEET_MODIFIED
:
528 case SFX_STYLESHEET_CHANGED
:
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();
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());
554 pNewStSh
= pModel
->GetDefaultStyleSheet();
558 // remove used style, it's erased or in destruction
559 ImpRemoveStyleSheet();
563 ImpAddStyleSheet(pNewStSh
, sal_True
);
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
578 rObj
.BroadcastObjectChange();
580 //if(pPage && pPage->IsInserted())
582 // rObj.BroadcastObjectChange();
585 rObj
.SendUserCall(SDRUSERCALL_CHGATTR
, aBoundRect
);
587 bHintUsed
= sal_True
;
591 // When it's the BackgroundObject, set the MasterPage to changed to
592 // get a refresh for the evtl. changed BackgroundStyle
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
);
600 && pSimpleHint
->GetId() == SFX_HINT_DATACHANGED
601 && GetSdrObject().IsMasterPageBackgroundObject())
603 GetSdrObject().GetPage()->ActionChanged();
608 // forward to SdrObject ATM. Not sure if this will be necessary
610 GetSdrObject().Notify(rBC
, rHint
);
613 } // end of namespace properties
614 } // end of namespace sdr
616 //////////////////////////////////////////////////////////////////////////////