bump product version to 5.0.4.1
[LibreOffice.git] / forms / source / xforms / propertysetbase.hxx
blob7fdb2124b3c2b9f7c4eb60512133047a98eec29a
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 .
19 #ifndef INCLUDED_FORMS_SOURCE_XFORMS_PROPERTYSETBASE_HXX
20 #define INCLUDED_FORMS_SOURCE_XFORMS_PROPERTYSETBASE_HXX
22 #include <cppuhelper/weak.hxx>
23 #include <com/sun/star/lang/XTypeProvider.hpp>
24 #include <comphelper/propstate.hxx>
25 #include <comphelper/propertysetinfo.hxx>
26 #include <comphelper/proparrhlp.hxx>
27 #include <rtl/ref.hxx>
28 #include <salhelper/simplereferenceobject.hxx>
30 // include for inlined helper function below
31 #include <com/sun/star/lang/IllegalArgumentException.hpp>
32 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <map>
36 namespace com { namespace sun { namespace star { namespace uno {
37 class Any;
38 class RuntimeException;
39 template<class T> class Sequence;
40 } } } }
42 /** base class which encapsulates accessing (reading/writing) concrete property values
44 class PropertyAccessorBase : public salhelper::SimpleReferenceObject
46 protected:
47 PropertyAccessorBase() { }
48 virtual ~PropertyAccessorBase();
50 public:
52 virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const = 0;
53 virtual void setValue( const com::sun::star::uno::Any& rValue ) = 0;
54 virtual void getValue( com::sun::star::uno::Any& rValue ) const = 0;
55 virtual bool isWriteable() const = 0;
59 /** helper class for implementing property accessors through public member functions
61 template< typename CLASS, typename VALUE, class WRITER, class READER >
62 class GenericPropertyAccessor : public PropertyAccessorBase
64 public:
65 typedef WRITER Writer;
66 typedef READER Reader;
68 private:
69 CLASS* m_pInstance;
70 Writer m_pWriter;
71 Reader m_pReader;
73 public:
74 GenericPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
75 :m_pInstance( pInstance )
76 ,m_pWriter( pWriter )
77 ,m_pReader( pReader )
81 virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const SAL_OVERRIDE
83 VALUE aVal;
84 return ( rValue >>= aVal );
87 virtual void setValue( const com::sun::star::uno::Any& rValue ) SAL_OVERRIDE
89 VALUE aTypedVal = VALUE();
90 OSL_VERIFY( rValue >>= aTypedVal );
91 (m_pInstance->*m_pWriter)( aTypedVal );
94 virtual void getValue( com::sun::star::uno::Any& rValue ) const SAL_OVERRIDE
96 rValue = com::sun::star::uno::makeAny( (m_pInstance->*m_pReader)() );
99 virtual bool isWriteable() const SAL_OVERRIDE
101 return m_pWriter != 0;
105 /** helper class for implementing property accessors via non-UNO methods
107 template< typename CLASS, typename VALUE >
108 class DirectPropertyAccessor
109 :public GenericPropertyAccessor < CLASS
110 , VALUE
111 , void (CLASS::*)( const VALUE& )
112 , VALUE (CLASS::*)() const
115 protected:
116 typedef void (CLASS::*Writer)( const VALUE& );
117 typedef VALUE (CLASS::*Reader)() const;
118 public:
119 DirectPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
120 :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
125 /** helper class for implementing non-UNO accessors to a boolean property
127 template< typename CLASS, typename DUMMY >
128 class BooleanPropertyAccessor
129 :public GenericPropertyAccessor < CLASS
130 , bool
131 , void (CLASS::*)( bool )
132 , bool (CLASS::*)() const
135 protected:
136 typedef void (CLASS::*Writer)( bool );
137 typedef bool (CLASS::*Reader)() const;
138 public:
139 BooleanPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
140 :GenericPropertyAccessor< CLASS, bool, Writer, Reader >( pInstance, pWriter, pReader )
145 /** helper class for implementing property accessors via UNO methods
147 template< typename CLASS, typename VALUE >
148 class APIPropertyAccessor
149 :public GenericPropertyAccessor < CLASS
150 , VALUE
151 , void (SAL_CALL CLASS::*)( const VALUE& )
152 , VALUE (SAL_CALL CLASS::*)()
155 protected:
156 typedef void (SAL_CALL CLASS::*Writer)( const VALUE& );
157 typedef VALUE (SAL_CALL CLASS::*Reader)();
158 public:
159 APIPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
160 :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
165 /** bridges two XPropertySet helper implementations
167 The <type scope="comphelper">OStatefulPropertySet</type> (basically, the
168 <type scope="cppu">OPropertySetHelper</type>) implements a comprehensive framework
169 for property sets, including property change notifications.
170 However, it lacks some easy possibilities to declare the supported properties.
171 Other helper structs and classes allow for this, but are lacking needed features
172 such as property change notifications.
174 The <type>PropertySetBase</type> bridges various implementations,
175 so you have the best of both worlds.
177 class PropertySetBase : public ::comphelper::OStatefulPropertySet
179 private:
180 typedef com::sun::star::uno::Any Any_t;
182 typedef ::std::map< const sal_Int32, ::rtl::Reference< PropertyAccessorBase > > PropertyAccessors;
183 typedef ::std::vector< ::com::sun::star::beans::Property > PropertyArray;
184 typedef ::std::map< const sal_Int32, Any_t > PropertyValueCache;
186 PropertyArray m_aProperties;
187 cppu::IPropertyArrayHelper* m_pProperties;
188 PropertyAccessors m_aAccessors;
189 PropertyValueCache m_aCache;
191 protected:
192 PropertySetBase();
193 virtual ~PropertySetBase();
195 /** registers a new property to be supported by this instance
196 @param rProperty
197 the descriptor for the to-be-supported property
198 @param rAccessor
199 an instance which is able to provide read and possibly write access to
200 the property.
201 @precond
202 Must not be called after any of the property set related UNO interfaces
203 has been used. Usually, you will do a number of <member>registerProperty</member>
204 calls in the constructor of your class.
206 void registerProperty(
207 const com::sun::star::beans::Property& rProperty,
208 const ::rtl::Reference< PropertyAccessorBase >& rAccessor
211 /** notifies a change in a given property value, if necessary
213 The necessity of the notification is determined by a cached value for the given
214 property. Caching happens after notification.
216 That is, when you call <member>notifyAndCachePropertyValue</member> for the first time,
217 a value for the given property is default constructed, and considered to be the "old value".
218 If this value differs from the current value, then this change is notified to all interested
219 listeners. Finally, the current value is remembered.
221 Subsequent calls to <member>notifyAndCachePropertyValue</member> use the remembered value as
222 "old value", and from then on behave as the first call.
224 @param nHandle
225 the handle of the property. Must denote a property supported by this instance, i.e.
226 one previously registered via <member>registerProperty</member>.
228 @precond
229 our ref count must not be 0. The reason is that during this method's execution,
230 the instance might be acquired and released, which would immediately destroy
231 the instance if it has a ref count of 0.
233 @seealso initializePropertyValueCache
235 void notifyAndCachePropertyValue( sal_Int32 nHandle );
237 /** initializes the property value cache for the given property, with its current value
239 Usually used to initialize the cache with values which are different from default
240 constructed values. Say you have a boolean property whose initial state
241 is <TRUE/>. Say you call <member>notifyAndCachePropertyValue</member> the first time: it will
242 default construct the "old value" for this property as <FALSE/>, and thus <b>not</b> do
243 any notifications if the "current value" is also <FALSE/> - which might be wrong, since
244 the guessing of the "old value" differed from the real initial value which was <TRUE/>.
246 Too confusing? Okay, than just call this method for every property you have.
248 @param nHandle
249 the handle of the property. Must denote a property supported by this instance, i.e.
250 one previously registered via <member>registerProperty</member>.
251 @param rValue
252 the value to cache
253 @seealso notifyAndCachePropertyValue
255 void initializePropertyValueCache( sal_Int32 nHandle );
257 /// OPropertysetHelper methods
258 virtual sal_Bool SAL_CALL convertFastPropertyValue( Any_t& rConvertedValue, Any_t& rOldValue, sal_Int32 nHandle, const Any_t& rValue )
259 throw (::com::sun::star::lang::IllegalArgumentException) SAL_OVERRIDE;
260 virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any_t& rValue )
261 throw (::com::sun::star::uno::Exception, std::exception) SAL_OVERRIDE;
262 virtual void SAL_CALL getFastPropertyValue( Any_t& rValue, sal_Int32 nHandle ) const SAL_OVERRIDE;
264 virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
265 virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
267 public:
268 /// helper struct for granting selective access to some notification-related methods
269 struct NotifierAccess { friend struct PropertyChangeNotifier; private: NotifierAccess() { } };
270 /** retrieves the current property value for the given handle
271 @param nHandle
272 the handle of the property. Must denote a property supported by this instance, i.e.
273 one previously registered via <member>registerProperty</member>.
274 @see registerProperty
276 inline void getCurrentPropertyValueByHandle( sal_Int32 nHandle, Any_t& /* [out] */ rValue, const NotifierAccess& ) const
278 getFastPropertyValue( rValue, nHandle );
281 /** notifies a change in a given property to all interested listeners
283 inline void notifyPropertyChange( sal_Int32 nHandle, const Any_t& rOldValue, const Any_t& rNewValue, const NotifierAccess& ) const
285 const_cast< PropertySetBase* >( this )->firePropertyChange( nHandle, rNewValue, rOldValue );
288 using ::comphelper::OStatefulPropertySet::getFastPropertyValue;
290 private:
291 /** locates a property given by handle
292 @param nHandle
293 the handle of the property. Must denote a property supported by this instance, i.e.
294 one previously registered via <member>registerProperty</member>.
295 @see registerProperty
297 PropertyAccessorBase& locatePropertyHandler( sal_Int32 nHandle ) const;
300 /** a helper class for notifying property changes in a <type>PropertySetBase</type> instance.
302 You can create an instance of this class on the stack of a method which is to programmatically
303 change the value of a property. In its constructor, the instance will acquire the current property
304 value, and in its destructor, it will notify the change of this property's value (if necessary).
306 You do not need this class if you are modifying property values by using the X(Fast|Multi)PropertSet
307 methods, since those already care for property notifications. You only need it if you're changing
308 the internal representation of your property directly.
310 Also note that usually, notifications in the UNO world should be done without a locked mutex. So
311 if you use this class in conjunction with a <type>MutexGuard</type>, ensure that you <b>first</b>
312 instantiate the <type>PropertyChangeNotifier</type>, and <b>then</b> the <type>MutexGuard</type>,
313 so your mutex is released before the notification happens.
315 struct PropertyChangeNotifier
317 private:
318 const PropertySetBase& m_rPropertySet;
319 sal_Int32 m_nHandle;
320 com::sun::star::uno::Any m_aOldValue;
322 public:
323 /** constructs a PropertyChangeNotifier
324 @param rPropertySet
325 the property set implementation whose property is going to be changed. Note
326 that this property set implementation must live at least as long as the
327 PropertyChangeNotifier instance does.
328 @param nHandle
329 the handle of the property which is going to be changed. Must be a valid property
330 handle for the given <arg>rPropertySet</arg>
332 inline PropertyChangeNotifier( const PropertySetBase& rPropertySet, sal_Int32 nHandle )
333 :m_rPropertySet( rPropertySet )
334 ,m_nHandle( nHandle )
336 m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, m_aOldValue, PropertySetBase::NotifierAccess() );
338 inline ~PropertyChangeNotifier()
340 com::sun::star::uno::Any aNewValue;
341 m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, aNewValue, PropertySetBase::NotifierAccess() );
342 if ( aNewValue != m_aOldValue )
344 m_rPropertySet.notifyPropertyChange( m_nHandle, m_aOldValue, aNewValue, PropertySetBase::NotifierAccess() );
350 #define PROPERTY_FLAGS( NAME, TYPE, FLAG ) com::sun::star::beans::Property( \
351 OUString( #NAME, sizeof( #NAME ) - 1, RTL_TEXTENCODING_ASCII_US ), \
352 HANDLE_##NAME, cppu::UnoType<TYPE>::get(), FLAG )
353 #define PROPERTY( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND )
354 #define PROPERTY_RO( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND | com::sun::star::beans::PropertyAttribute::READONLY )
356 #endif
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */