1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_SVL_POOLITEM_HXX
21 #define INCLUDED_SVL_POOLITEM_HXX
22 
23 #include <sal/config.h>
24 
25 #include <memory>
26 
27 #include <com/sun/star/uno/Any.hxx>
28 #include <svl/hint.hxx>
29 #include <svl/svldllapi.h>
30 #include <svl/typedwhich.hxx>
31 #include <tools/mapunit.hxx>
32 #include <tools/long.hxx>
33 #include <boost/property_tree/ptree_fwd.hpp>
34 
35 class IntlWrapper;
36 
37 enum class SfxItemKind : sal_Int8
38 {
39    NONE,
40    DeleteOnIdle,
41    StaticDefault,
42    PoolDefault
43 };
44 
45 #define SFX_ITEMS_OLD_MAXREF                0xffef
46 #define SFX_ITEMS_MAXREF                    0xfffffffe
47 #define SFX_ITEMS_SPECIAL                   0xffffffff
48 
49 #define CONVERT_TWIPS                       0x80    // Uno conversion for measurement (for MemberId)
50 
51 // warning, if there is no boolean inside the any this will always return the value false
Any2Bool(const css::uno::Any & rValue)52 inline bool Any2Bool( const css::uno::Any&rValue )
53 {
54     bool bValue = false;
55     if( !(rValue >>= bValue) )
56     {
57         sal_Int32 nNum = 0;
58         if( rValue >>= nNum )
59             bValue = nNum != 0;
60     }
61 
62     return bValue;
63 }
64 
65 /*
66  * The values of this enum describe the degree of textual
67  * representation of an item after calling the virtual
68  * method <SfxPoolItem::GetPresentation()const>.
69  */
70 enum class SfxItemPresentation
71 {
72     Nameless,
73     Complete
74 };
75 
76 /**
77  * These values have to match the values in the
78  * css::frame::status::ItemState IDL
79  * to be found at offapi/com/sun/star/frame/status/ItemState.idl
80 */
81 enum class SfxItemState {
82 
83     /** Specifies an unknown state. */
84     UNKNOWN  = 0,
85 
86     /** Specifies that the property is currently disabled. */
87     DISABLED = 0x0001,
88 
89     /** Specifies that the property is currently in a don't care state.
90      * <br/>
91      * This is normally used if a selection provides more than one state
92      * for a property at the same time.
93      */
94     DONTCARE = 0x0010,
95 
96     /** Specifies that the property is currently in a default state. */
97     DEFAULT  = 0x0020,
98 
99     /** The property has been explicitly set to a given value hence we know
100      * we are not taking the default value.
101      * <br/>
102      * For example, you may want to get the font color and it might either
103      * be the default one or one that has been explicitly set.
104     */
105     SET      = 0x0040
106 };
107 
108 #define INVALID_POOL_ITEM reinterpret_cast<SfxPoolItem*>(-1)
109 
110 class SfxItemPool;
111 class SfxItemSet;
112 typedef struct _xmlTextWriter* xmlTextWriterPtr;
113 
114 class SVL_DLLPUBLIC SfxPoolItem
115 {
116 friend class SfxItemPool;
117 friend class SfxItemDisruptor_Impl;
118 friend class SfxItemPoolCache;
119 friend class SfxItemSet;
120 friend class SfxVoidItem;
121 
122     mutable sal_uInt32 m_nRefCount;
123     sal_uInt16  m_nWhich;
124     SfxItemKind  m_nKind;
125 
126 private:
127     inline void              SetRefCount(sal_uInt32 n);
128     inline void              SetKind( SfxItemKind n );
129 public:
130     inline void              AddRef(sal_uInt32 n = 1) const;
131 private:
132     inline sal_uInt32        ReleaseRef(sal_uInt32 n = 1) const;
133 
134 protected:
135                              explicit SfxPoolItem( sal_uInt16 nWhich = 0 );
SfxPoolItem(const SfxPoolItem & rCopy)136                              SfxPoolItem( const SfxPoolItem& rCopy)
137                                  : SfxPoolItem(rCopy.m_nWhich) {}
138 
139 public:
140     virtual                  ~SfxPoolItem();
141 
SetWhich(sal_uInt16 nId)142     void                     SetWhich( sal_uInt16 nId )
143                              {
144                                  // can only change the Which before we are in a set
145                                  assert(m_nRefCount==0);
146                                  m_nWhich = nId;
147                              }
Which() const148     sal_uInt16               Which() const { return m_nWhich; }
149     // StaticWhichCast asserts if the TypedWhichId is not matching its type, otherwise it returns a reference.
150     // You can use StaticWhichCast when you are sure about the type at compile time -- like a static_cast.
StaticWhichCast(TypedWhichId<T> nId)151     template<class T> T& StaticWhichCast(TypedWhichId<T> nId)
152     {
153         (void)nId;
154         assert(nId == m_nWhich);
155         assert(dynamic_cast<T*>(this));
156         return *static_cast<T*>(this);
157     }
StaticWhichCast(TypedWhichId<T> nId) const158     template<class T> const T& StaticWhichCast(TypedWhichId<T> nId) const
159     {
160         (void)nId;
161         assert(nId == m_nWhich);
162         assert(dynamic_cast<const T*>(this));
163         return *static_cast<const T*>(this);
164     }
165     // DynamicWhichCast returns nullptr if the TypedWhichId is not matching its type, otherwise it returns a typed pointer.
166     // it asserts if the TypedWhichId matches its Which, but not the RTTI type.
167     // You can use DynamicWhichCast when you are not sure about the type at compile time -- like a dynamic_cast.
DynamicWhichCast(TypedWhichId<T> nId)168     template<class T> T* DynamicWhichCast(TypedWhichId<T> nId)
169     {
170         if(m_nWhich != nId)
171             return nullptr;
172         assert(dynamic_cast<T*>(this));
173         return static_cast<T*>(this);
174     }
DynamicWhichCast(TypedWhichId<T> nId) const175     template<class T> const T* DynamicWhichCast(TypedWhichId<T> nId) const
176     {
177         if(m_nWhich != nId)
178             return nullptr;
179         assert(dynamic_cast<const T*>(this));
180         return static_cast<const T*>(this);
181     }
182     virtual bool             operator==( const SfxPoolItem& ) const = 0;
operator !=(const SfxPoolItem & rItem) const183     bool                     operator!=( const SfxPoolItem& rItem ) const
184                              { return !(*this == rItem); }
185 
186     // Sorting is only used for faster searching in a pool which contains large quantities
187     // of a single kind of pool item.
operator <(const SfxPoolItem &) const188     virtual bool             operator<( const SfxPoolItem& ) const { assert(false); return false; }
IsSortable() const189     virtual bool             IsSortable() const { return false; }
190 
191     /**  @return true if it has a valid string representation */
192     virtual bool             GetPresentation( SfxItemPresentation ePresentation,
193                                     MapUnit eCoreMetric,
194                                     MapUnit ePresentationMetric,
195                                     OUString &rText,
196                                     const IntlWrapper& rIntlWrapper ) const;
197 
198     virtual void             ScaleMetrics( tools::Long lMult, tools::Long lDiv );
199     virtual bool             HasMetrics() const;
200 
201     virtual bool             QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId = 0 ) const;
202     virtual bool             PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId );
203 
204     virtual SfxPoolItem*     Clone( SfxItemPool *pPool = nullptr ) const = 0;
205     // clone and call SetWhich
206     std::unique_ptr<SfxPoolItem> CloneSetWhich( sal_uInt16 nNewWhich ) const;
CloneSetWhich(TypedWhichId<T> nId) const207     template<class T> std::unique_ptr<T> CloneSetWhich( TypedWhichId<T> nId ) const
208     {
209         return std::unique_ptr<T>(static_cast<T*>(CloneSetWhich(sal_uInt16(nId)).release()));
210     }
211 
GetRefCount() const212     sal_uInt32               GetRefCount() const { return m_nRefCount; }
GetKind() const213     SfxItemKind       GetKind() const { return m_nKind; }
214     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
215     virtual boost::property_tree::ptree dumpAsJSON() const;
216 
217     /** Only SfxVoidItem shall and must return true for this.
218 
219         This avoids costly calls to dynamic_cast<const SfxVoidItem*>()
220         specifically in SfxItemSet::GetItemState()
221      */
222     virtual bool             IsVoidItem() const;
223 
224 private:
225     SfxPoolItem&             operator=( const SfxPoolItem& ) = delete;
226 };
227 
SetRefCount(sal_uInt32 n)228 inline void SfxPoolItem::SetRefCount(sal_uInt32 n)
229 {
230     m_nRefCount = n;
231     m_nKind = SfxItemKind::NONE;
232 }
233 
SetKind(SfxItemKind n)234 inline void SfxPoolItem::SetKind( SfxItemKind n )
235 {
236     m_nRefCount = SFX_ITEMS_SPECIAL;
237     m_nKind = n;
238 }
239 
AddRef(sal_uInt32 n) const240 inline void SfxPoolItem::AddRef(sal_uInt32 n) const
241 {
242     assert(m_nRefCount <= SFX_ITEMS_MAXREF && "AddRef with non-Pool-Item");
243     assert(n <= SFX_ITEMS_MAXREF - m_nRefCount && "AddRef: refcount overflow");
244     m_nRefCount += n;
245 }
246 
ReleaseRef(sal_uInt32 n) const247 inline sal_uInt32 SfxPoolItem::ReleaseRef(sal_uInt32 n) const
248 {
249     assert(m_nRefCount <= SFX_ITEMS_MAXREF && "ReleaseRef with non-Pool-Item");
250     assert(n <= m_nRefCount);
251     m_nRefCount -= n;
252     return m_nRefCount;
253 }
254 
IsPoolDefaultItem(const SfxPoolItem * pItem)255 inline bool IsPoolDefaultItem(const SfxPoolItem *pItem )
256 {
257     return pItem && pItem->GetKind() == SfxItemKind::PoolDefault;
258 }
259 
IsStaticDefaultItem(const SfxPoolItem * pItem)260 inline bool IsStaticDefaultItem(const SfxPoolItem *pItem )
261 {
262     return pItem && pItem->GetKind() == SfxItemKind::StaticDefault;
263 }
264 
IsDefaultItem(const SfxPoolItem * pItem)265 inline bool IsDefaultItem( const SfxPoolItem *pItem )
266 {
267     return pItem && (pItem->GetKind() == SfxItemKind::StaticDefault || pItem->GetKind() == SfxItemKind::PoolDefault);
268 }
269 
IsPooledItem(const SfxPoolItem * pItem)270 inline bool IsPooledItem( const SfxPoolItem *pItem )
271 {
272     return pItem && pItem->GetRefCount() > 0 && pItem->GetRefCount() <= SFX_ITEMS_MAXREF;
273 }
274 
IsInvalidItem(const SfxPoolItem * pItem)275 inline bool IsInvalidItem(const SfxPoolItem *pItem)
276 {
277     return pItem == INVALID_POOL_ITEM;
278 }
279 
280 class SVL_DLLPUBLIC SfxVoidItem final: public SfxPoolItem
281 {
282 public:
283                             static SfxPoolItem* CreateDefault();
284                             explicit SfxVoidItem( sal_uInt16 nWhich );
285                             virtual ~SfxVoidItem() override;
286 
287     SfxVoidItem(SfxVoidItem const &) = default;
288     SfxVoidItem(SfxVoidItem &&) = default;
289     SfxVoidItem & operator =(SfxVoidItem const &) = delete; // due to SfxPoolItem
290     SfxVoidItem & operator =(SfxVoidItem &&) = delete; // due to SfxPoolItem
291 
292     virtual bool            operator==( const SfxPoolItem& ) const override;
293 
294     virtual bool GetPresentation( SfxItemPresentation ePres,
295                                     MapUnit eCoreMetric,
296                                     MapUnit ePresMetric,
297                                     OUString &rText,
298                                     const IntlWrapper& ) const override;
299     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;
300 
301     // create a copy of itself
302     virtual SfxVoidItem*    Clone( SfxItemPool *pPool = nullptr ) const override;
303 
304     /** Always returns true as this is an SfxVoidItem. */
305     virtual bool            IsVoidItem() const override;
306 };
307 
308 class SVL_DLLPUBLIC SfxSetItem: public SfxPoolItem
309 {
310     std::unique_ptr<SfxItemSet>  pSet;
311 
312     SfxSetItem & operator=( const SfxSetItem& ) = delete;
313 
314 public:
315                             SfxSetItem( sal_uInt16 nWhich, std::unique_ptr<SfxItemSet> &&pSet );
316                             SfxSetItem( sal_uInt16 nWhich, const SfxItemSet &rSet );
317                             SfxSetItem( const SfxSetItem&, SfxItemPool *pPool = nullptr );
318                             virtual ~SfxSetItem() override;
319 
320     virtual bool            operator==( const SfxPoolItem& ) const override;
321 
322     virtual bool GetPresentation( SfxItemPresentation ePres,
323                                     MapUnit eCoreMetric,
324                                     MapUnit ePresMetric,
325                                     OUString &rText,
326                                     const IntlWrapper& ) const override;
327 
328     // create a copy of itself
329     virtual SfxSetItem*     Clone( SfxItemPool *pPool = nullptr ) const override = 0;
330 
GetItemSet() const331     const SfxItemSet&       GetItemSet() const
332                             { return *pSet; }
GetItemSet()333     SfxItemSet&             GetItemSet()
334                             { return *pSet; }
335 };
336 
337 class SVL_DLLPUBLIC SfxPoolItemHint final : public SfxHint
338 {
339     SfxPoolItem* pObj;
340 public:
SfxPoolItemHint(SfxPoolItem * Object)341     explicit SfxPoolItemHint( SfxPoolItem* Object ) : pObj(Object) {}
GetObject() const342     SfxPoolItem* GetObject() const { return pObj; }
343 };
344 
345 #endif
346 
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
348