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 .
22 #include <config_options.h>
23 #include <rtl/ref.hxx>
24 #include <svl/poolitem.hxx>
25 #include <svl/svldllapi.h>
26 #include <svl/typedwhich.hxx>
27 #include <svl/whichranges.hxx>
30 #include <unordered_set>
31 #include <unordered_map>
32 #include <o3tl/sorted_vector.hxx>
33 #include <salhelper/simplereferenceobject.hxx>
34 #include <svl/SfxBroadcaster.hxx>
36 // flag definitions to be used for _nItemInfoFlags
38 #define SFX_ITEMINFOFLAG_NONE 0x0000
40 // Defines if this Item needs to be registered at the pool
41 // to make it accessible for the GetItemSurrogates call. It
42 // will not be included when this flag is not set, but also
43 // needs no registration. There are SAL_INFO calls in the
44 // GetItemSurrogates impl that will mention that
45 #define SFX_ITEMINFOFLAG_SUPPORT_SURROGATE 0x0001
47 class SVL_DLLPUBLIC ItemInfo
51 sal_uInt16 m_nItemInfoFlags
;
54 ItemInfo(sal_uInt16 nWhich
, sal_uInt16 nSlotID
, sal_uInt16 nItemInfoFlags
)
55 : m_nWhich(nWhich
), m_nSlotID(nSlotID
), m_nItemInfoFlags(nItemInfoFlags
) {}
56 ItemInfo(const ItemInfo
& rIemInfo
) = default;
57 virtual ~ItemInfo() = default;
59 sal_uInt16
getWhich() const { return m_nWhich
; }
60 virtual const SfxPoolItem
* getItem() const = 0;
61 sal_uInt16
getSlotID() const { return m_nSlotID
; }
62 sal_uInt16
getItemInfoFlags() const { return m_nItemInfoFlags
; }
65 class SVL_DLLPUBLIC ItemInfoStatic
: public ItemInfo
67 friend class ItemInfoPackage
;
68 void setItem(SfxPoolItem
* pItem
)
71 pItem
->setStaticDefault();
75 std::unique_ptr
<const SfxPoolItem
> m_pItem
;
78 ItemInfoStatic(sal_uInt16 nWhich
, SfxPoolItem
* pItem
, sal_uInt16 nSlotID
, sal_uInt16 nItemInfoFlags
)
79 : ItemInfo(nWhich
, nSlotID
, nItemInfoFlags
)
80 , m_pItem(pItem
) { if(nullptr != pItem
) pItem
->setStaticDefault(); }
82 virtual const SfxPoolItem
* getItem() const override
{ return m_pItem
.get(); }
85 class SVL_DLLPUBLIC ItemInfoDynamic
: public ItemInfo
87 std::unique_ptr
<const SfxPoolItem
> m_pItem
;
90 ItemInfoDynamic(const ItemInfo
& rItemInfo
, SfxPoolItem
* pItem
)
92 , m_pItem(pItem
) { if(nullptr != pItem
) pItem
->setDynamicDefault(); }
94 virtual const SfxPoolItem
* getItem() const override
{ return m_pItem
.get(); }
97 class UNLESS_MERGELIBS(SVL_DLLPUBLIC
) ItemInfoUser
: public ItemInfo
99 const SfxPoolItem
* m_pItem
;
102 ItemInfoUser(const ItemInfo
& rItemInfo
, SfxItemPool
& rItemPool
, const SfxPoolItem
& rItem
, bool bPassingOwnership
= false);
103 virtual ~ItemInfoUser();
105 virtual const SfxPoolItem
* getItem() const override
{ return m_pItem
; }
108 typedef std::unordered_map
<sal_uInt16
, sal_uInt16
> SlotIDToWhichIDMap
;
110 class SVL_DLLPUBLIC ItemInfoPackage
113 // this is needed for on-demand creation of static entries in constructors
114 // derived from ItemInfoPackage or implementations of ::getItemInfo(). This
115 // takes ownership of the item
116 static void setItemAtItemInfoStatic(SfxPoolItem
* pItem
, ItemInfoStatic
& rItemInfo
) { rItemInfo
.setItem(pItem
); }
119 // mechanism for buffered SlotIDToWhichIDMap
120 virtual const ItemInfoStatic
& getItemInfoStatic(size_t nIndex
) const = 0;
121 mutable SlotIDToWhichIDMap maSlotIDToWhichIDMap
;
124 ItemInfoPackage() = default;
125 virtual ~ItemInfoPackage() = default;
127 virtual size_t size() const = 0;
128 virtual const ItemInfo
& getItemInfo(size_t nIndex
, SfxItemPool
& rPool
) = 0;
129 virtual const ItemInfo
& getExistingItemInfo(size_t /*nIndex*/);
130 const SlotIDToWhichIDMap
& getSlotIDToWhichIDMap() const;
133 typedef std::unordered_set
<SfxItemSet
*> registeredSfxItemSets
;
134 class SfxPoolItemHolder
;
135 typedef std::unordered_set
<SfxPoolItemHolder
*> registeredSfxPoolItemHolders
;
136 typedef std::vector
<const SfxPoolItem
*> ItemSurrogates
;
137 typedef std::unordered_map
<sal_uInt16
, const ItemInfo
*> userItemInfos
;
138 typedef std::vector
<const ItemInfo
*> itemInfoVector
;
140 /** Base class for providers of defaults of SfxPoolItems.
142 * The derived classes hold the concrete (const) instances which are referenced in several places
143 * (usually within a single document).
144 * This helps to lower the amount of calls to lifecycle methods, speeds up comparisons within a document
145 * and facilitates loading and saving of attributes.
147 class SVL_DLLPUBLIC SfxItemPool
: public salhelper::SimpleReferenceObject
149 friend class SfxItemSet
;
150 friend class SfxPoolItemHolder
;
151 friend class SfxAllItemSet
;
153 // allow ItemSetTooling to access
154 friend SfxPoolItem
const* implCreateItemEntry(SfxItemPool
&, SfxPoolItem
const*, bool);
155 friend void implCleanupItemEntry(SfxPoolItem
const*);
159 SfxItemPool
* mpMaster
;
160 rtl::Reference
<SfxItemPool
> mpSecondary
;
161 mutable WhichRangesContainer maPoolRanges
;
166 registeredSfxItemSets maRegisteredSfxItemSets
;
167 registeredSfxPoolItemHolders maRegisteredSfxPoolItemHolders
;
168 bool mbShutdownHintSent
;
170 itemInfoVector maItemInfos
;
171 userItemInfos maUserItemInfos
;
172 const SlotIDToWhichIDMap
* mpSlotIDToWhichIDMap
;
175 void registerItemInfoPackage(
176 ItemInfoPackage
& rPackage
,
177 const std::function
<SfxPoolItem
*(sal_uInt16
)>& rCallback
= std::function
<SfxPoolItem
*(sal_uInt16
)>());
179 const ItemInfo
* impCheckItemInfoForClone(const ItemInfo
* pInfo
);
180 void impClearUserDefault(userItemInfos::iterator
& rHit
);
181 void impCreateUserDefault(const SfxPoolItem
& rItem
);
183 void cleanupItemInfos();
186 sal_uInt16
GetIndex_Impl(sal_uInt16 nWhich
) const
188 if (IsInRange(nWhich
))
189 return nWhich
- mnStart
;
190 assert(false && "missing bounds check before use");
193 sal_uInt16
GetSize_Impl() const { return mnEnd
- mnStart
+ 1; }
194 SfxItemPool
* getTargetPool(sal_uInt16 nWhich
) const;
196 // moved to private: use the access methods, e.g. NeedsSurrogateSupport
197 SVL_DLLPRIVATE
bool CheckItemInfoFlag(sal_uInt16 nWhich
, sal_uInt16 nMask
) const;
198 SVL_DLLPRIVATE
bool CheckItemInfoFlag_Impl(sal_uInt16 nPos
, sal_uInt16 nMask
) const
199 { return maItemInfos
[nPos
]->getItemInfoFlags() & nMask
; }
201 void registerItemSet(SfxItemSet
& rSet
);
202 void unregisterItemSet(SfxItemSet
& rSet
);
204 void registerPoolItemHolder(SfxPoolItemHolder
& rHolder
);
205 void unregisterPoolItemHolder(SfxPoolItemHolder
& rHolder
);
208 // for default SfxItemSet::CTOR, set default WhichRanges
209 const WhichRangesContainer
& GetMergedIdRanges() const;
212 static inline void AddRef(const SfxPoolItem
& rItem
);
213 static inline sal_uInt32
ReleaseRef(const SfxPoolItem
& rItem
, sal_uInt32 n
= 1);
216 SfxItemPool(const SfxItemPool
&rPool
);
217 SfxItemPool(const OUString
&rName
);
218 virtual ~SfxItemPool();
220 SfxBroadcaster
& BC();
222 // UserDefaults: Every PoolDefault can be 'overloaded' with a user-defined
223 // default. This is then owned by the pool. The read access is limited
224 // to check the UserDefaults, so it *will* return nullptr if none is set
225 void SetUserDefaultItem( const SfxPoolItem
& );
226 const SfxPoolItem
* GetUserDefaultItem( sal_uInt16 nWhich
) const;
227 template<class T
> const T
* GetUserDefaultItem( TypedWhichId
<T
> nWhich
) const
228 { return static_cast<const T
*>(GetUserDefaultItem(sal_uInt16(nWhich
))); }
229 void ResetUserDefaultItem( sal_uInt16 nWhich
);
231 // PoolDefaults: Owned by the pool. The read access will only return
232 // nullptr if the WhichID asked for is not in the range of the pool,
233 // making the request invalid.
234 const SfxPoolItem
* GetPoolDefaultItem(sal_uInt16 nWhich
) const;
235 template<class T
> const T
* GetPoolDefaultItem( TypedWhichId
<T
> nWhich
) const
236 { return static_cast<const T
*>(GetPoolDefaultItem(sal_uInt16(nWhich
))); }
238 // UserOrPoolDefaults: Combination of UserDefaults and PoolDefaults.
239 // UserDefaults will be preferred. If none is set for that WhichID,
240 // the PoolDefault will be returned.
241 // Note that read access will return a reference, but this will lead
242 // to an asserted error when the given WhichID is not in the range of
244 const SfxPoolItem
& GetUserOrPoolDefaultItem( sal_uInt16 nWhich
) const;
245 template<class T
> const T
& GetUserOrPoolDefaultItem( TypedWhichId
<T
> nWhich
) const
246 { return static_cast<const T
&>(GetUserOrPoolDefaultItem(sal_uInt16(nWhich
))); }
248 virtual MapUnit
GetMetric( sal_uInt16 nWhich
) const;
249 void SetDefaultMetric( MapUnit eNewMetric
);
250 MapUnit
GetDefaultMetric() const { return eDefMetric
; }
252 /** Request string representation of pool items.
254 This virtual function produces a string representation
255 from the respective SfxItemPool subclass' known SfxPoolItems.
257 Subclasses, please override this method, and handle
258 SfxPoolItems that don't return useful/complete information on
259 SfxPoolItem::GetPresentation()
261 This baseclass yields the unmodified string representation of
265 SfxPoolItem to query the string representation of
268 requested kind of representation - see SfxItemPresentation
271 requested unit of measure of the representation
274 string representation of 'rItem'
276 @return true if it has a valid string representation
278 virtual bool GetPresentation( const SfxPoolItem
& rItem
,
279 MapUnit ePresentationMetric
,
281 const IntlWrapper
& rIntlWrapper
) const;
282 virtual rtl::Reference
<SfxItemPool
> Clone() const;
283 const OUString
& GetName() const { return aName
; }
286 // SurrogateData callback helper for iterateItemSurrogates
290 virtual ~SurrogateData() = default;
291 SurrogateData(const SurrogateData
&) = default;
292 SurrogateData() = default;
294 // read-access to Item
295 virtual const SfxPoolItem
& getItem() const = 0;
297 // write-access when Item needs to be modified
298 virtual const SfxPoolItem
* setItem(std::unique_ptr
<SfxPoolItem
>) = 0;
301 // Iterate using a lambda/callback with read/write access to registered SfxPoolItems.
302 // If you use this (look for current usages) inside the callback you may
303 // return true; // to continue callback (like 'continue')
304 // return false; // to end callbacks (like 'break')
305 void iterateItemSurrogates(
307 const std::function
<bool(SfxItemPool::SurrogateData
& rData
)>& rItemCallback
) const;
309 // Read-only access to registered SfxPoolItems
310 // NOTE: In *no* case use const_cast and change those Items (!)
311 // Read commit text for more information
312 void GetItemSurrogates(ItemSurrogates
& rTarget
, sal_uInt16 nWhich
) const;
314 sal_uInt16
GetFirstWhich() const { return mnStart
; }
315 sal_uInt16
GetLastWhich() const { return mnEnd
; }
316 bool IsInRange( sal_uInt16 nWhich
) const { return nWhich
>= mnStart
&& nWhich
<= mnEnd
; }
318 void SetSecondaryPool( SfxItemPool
*pPool
);
319 SfxItemPool
* GetSecondaryPool() const { return mpSecondary
.get(); }
320 /* get the last pool by following the GetSecondaryPool chain */
321 SfxItemPool
* GetLastPoolInChain();
322 SfxItemPool
* GetMasterPool() const { return mpMaster
; }
323 void sendShutdownHint();
325 // syntactical sugar: direct call to not have to use the flag define
326 // and make the intention clearer
327 bool NeedsSurrogateSupport(sal_uInt16 nWhich
) const
328 { return CheckItemInfoFlag(nWhich
, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE
); }
330 // tries to translate back from SlotID to WhichID.
331 // If none is defined, return nSlot.
332 // If nSlot is not a SlotID, return nSlot.
333 sal_uInt16
GetWhichIDFromSlotID(sal_uInt16 nSlot
, bool bDeep
= true) const;
334 template<class T
> TypedWhichId
<T
> GetWhichIDFromSlotID(TypedWhichId
<T
> nSlot
, bool bDeep
= true) const
335 { return TypedWhichId
<T
>(GetWhichIDFromSlotID(sal_uInt16(nSlot
), bDeep
)); }
337 // get SlotID that may be registered in the SfxItemInfo for
338 // the given WhichID.
339 // If none is defined, return nWhich.
340 // If nWhich is not a WhichID, return nWhich.
341 sal_uInt16
GetSlotId( sal_uInt16 nWhich
) const;
343 // same as GetWhichIDFromSlotID, but returns 0 in error cases, so:
344 // If none is defined, return 0.
345 // If nSlot is not a SlotID, return 0.
346 sal_uInt16
GetTrueWhichIDFromSlotID( sal_uInt16 nSlot
, bool bDeep
= true ) const;
348 // same as GetSlotId, but returns 0 in error cases, so:
349 // If none is defined, return 0.
350 // If nWhich is not a WhichID, return 0.
351 sal_uInt16
GetTrueSlotId( sal_uInt16 nWhich
) const;
353 static bool IsWhich(sal_uInt16 nId
) { return nId
&& nId
<= SFX_WHICH_MAX
; }
354 static bool IsSlot(sal_uInt16 nId
) { return nId
&& nId
> SFX_WHICH_MAX
; }
357 const SfxItemPool
& operator=(const SfxItemPool
&) = delete;
359 //IDs below or equal are Which IDs, IDs above slot IDs
360 static const sal_uInt16 SFX_WHICH_MAX
= 4999;
363 // only the pool may manipulate the reference counts
364 inline void SfxItemPool::AddRef(const SfxPoolItem
& rItem
)
369 // only the pool may manipulate the reference counts
370 inline sal_uInt32
SfxItemPool::ReleaseRef(const SfxPoolItem
& rItem
, sal_uInt32 n
)
372 return rItem
.ReleaseRef(n
);
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */