update dev300-m58
[ooovba.git] / forms / source / xforms / propertysetbase.hxx
blob803df5294acbf3f250f5b399cddb69c6f9de26e7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propertysetbase.hxx,v $
10 * $Revision: 1.7 $
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 ************************************************************************/
30 #ifndef _PROPERTYSETBASE_HXX
31 #define _PROPERTYSETBASE_HXX
34 // include for parent class
35 #include <cppuhelper/weak.hxx>
36 #include <com/sun/star/lang/XTypeProvider.hpp>
37 #include <comphelper/propstate.hxx>
38 #include <comphelper/propertysetinfo.hxx>
39 #include <comphelper/proparrhlp.hxx>
40 #include <rtl/ref.hxx>
42 // include for inlined helper function below
43 #include <com/sun/star/lang/IllegalArgumentException.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <map>
48 // forward declarations for method arguments
49 namespace com { namespace sun { namespace star { namespace uno {
50 class Any;
51 class Type;
52 class RuntimeException;
53 template<class T> class Sequence;
54 } } } }
56 /** base class which encapsulates accessing (reading/writing) concrete property values
58 class PropertyAccessorBase : public ::rtl::IReference
60 private:
61 oslInterlockedCount m_refCount;
63 protected:
64 PropertyAccessorBase() : m_refCount( 0 ) { }
66 public:
67 virtual oslInterlockedCount SAL_CALL acquire();
68 virtual oslInterlockedCount SAL_CALL release();
70 virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const = 0;
71 virtual void setValue( const com::sun::star::uno::Any& rValue ) = 0;
72 virtual void getValue( com::sun::star::uno::Any& rValue ) const = 0;
73 virtual bool isWriteable() const = 0;
77 /** helper class for implementing property accessors through public member functions
79 template< typename CLASS, typename VALUE, class WRITER, class READER >
80 class GenericPropertyAccessor : public PropertyAccessorBase
82 public:
83 typedef WRITER Writer;
84 typedef READER Reader;
86 private:
87 CLASS* m_pInstance;
88 Writer m_pWriter;
89 Reader m_pReader;
91 public:
92 GenericPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
93 :m_pInstance( pInstance )
94 ,m_pWriter( pWriter )
95 ,m_pReader( pReader )
99 virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const
101 VALUE aVal;
102 return ( rValue >>= aVal );
105 virtual void setValue( const com::sun::star::uno::Any& rValue )
107 VALUE aTypedVal = VALUE();
108 OSL_VERIFY( rValue >>= aTypedVal );
109 (m_pInstance->*m_pWriter)( aTypedVal );
112 virtual void getValue( com::sun::star::uno::Any& rValue ) const
114 rValue = com::sun::star::uno::makeAny( (m_pInstance->*m_pReader)() );
117 virtual bool isWriteable() const
119 return m_pWriter != NULL;
123 /** helper class for implementing property accessors via non-UNO methods
125 template< typename CLASS, typename VALUE >
126 class DirectPropertyAccessor
127 :public GenericPropertyAccessor < CLASS
128 , VALUE
129 , void (CLASS::*)( const VALUE& )
130 , VALUE (CLASS::*)() const
133 protected:
134 typedef void (CLASS::*Writer)( const VALUE& );
135 typedef VALUE (CLASS::*Reader)() const;
136 public:
137 DirectPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
138 :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
143 /** helper class for implementing non-UNO accessors to a boolean property
145 template< typename CLASS, typename DUMMY >
146 class BooleanPropertyAccessor
147 :public GenericPropertyAccessor < CLASS
148 , bool
149 , void (CLASS::*)( bool )
150 , bool (CLASS::*)() const
153 protected:
154 typedef void (CLASS::*Writer)( bool );
155 typedef bool (CLASS::*Reader)() const;
156 public:
157 BooleanPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
158 :GenericPropertyAccessor< CLASS, bool, Writer, Reader >( pInstance, pWriter, pReader )
163 /** helper class for implementing property accessors via UNO methods
165 template< typename CLASS, typename VALUE >
166 class APIPropertyAccessor
167 :public GenericPropertyAccessor < CLASS
168 , VALUE
169 , void (SAL_CALL CLASS::*)( const VALUE& )
170 , VALUE (SAL_CALL CLASS::*)()
173 protected:
174 typedef void (SAL_CALL CLASS::*Writer)( const VALUE& );
175 typedef VALUE (SAL_CALL CLASS::*Reader)();
176 public:
177 APIPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
178 :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
183 /** bridges two XPropertySet helper implementations
185 The <type scope="comphelper">OStatefulPropertySet</type> (basically, the
186 <type scope="cppu">OPropertySetHelper</type>) implements a comprehensive framework
187 for property sets, including property change notifications.
188 However, it lacks some easy possibilities to declare the supported properties.
189 Other helper structs and classes allow for this, but are lacking needed features
190 such as property change notifications.
192 The <type>PropertySetBase</type> bridges various implementations,
193 so you have the best of both worlds.
195 class PropertySetBase : public ::comphelper::OStatefulPropertySet
197 private:
198 typedef com::sun::star::uno::Any Any_t;
200 typedef ::std::map< const sal_Int32, ::rtl::Reference< PropertyAccessorBase > > PropertyAccessors;
201 typedef ::std::vector< ::com::sun::star::beans::Property > PropertyArray;
202 typedef ::std::map< const sal_Int32, Any_t > PropertyValueCache;
204 PropertyArray m_aProperties;
205 cppu::IPropertyArrayHelper* m_pProperties;
206 PropertyAccessors m_aAccessors;
207 PropertyValueCache m_aCache;
209 protected:
210 PropertySetBase();
211 virtual ~PropertySetBase();
213 /** registers a new property to be supported by this instance
214 @param rProperty
215 the descriptor for the to-be-supported property
216 @param rAccessor
217 an instance which is able to provide read and possibly write access to
218 the property.
219 @precond
220 Must not be called after any of the property set related UNO interfaces
221 has been used. Usually, you will do a number of <member>registerProperty</member>
222 calls in the constructor of your class.
224 void registerProperty(
225 const com::sun::star::beans::Property& rProperty,
226 const ::rtl::Reference< PropertyAccessorBase >& rAccessor
229 /** notifies a change in a given property value, if necessary
231 The necessity of the notification is determined by a cached value for the given
232 property. Caching happens after notification.
234 That is, when you call <member>notifyAndCachePropertyValue</member> for the first time,
235 a value for the given property is default constructed, and considered to be the "old value".
236 If this value differs from the current value, then this change is notified to all interested
237 listeners. Finally, the current value is remembered.
239 Subsequent calls to <member>notifyAndCachePropertyValue</member> use the remembered value as
240 "old value", and from then on behave as the first call.
242 @param nHandle
243 the handle of the property. Must denote a property supported by this instance, i.e.
244 one previously registered via <member>registerProperty</member>.
246 @precond
247 our ref count must not be 0. The reason is that during this method's execution,
248 the instance might be acquired and released, which would immediately destroy
249 the instance if it has a ref count of 0.
251 @seealso initializePropertyValueCache
253 void notifyAndCachePropertyValue( sal_Int32 nHandle );
255 /** initializes the property value cache for the given property, with its current value
257 Usually used to initialize the cache with values which are different from default
258 constructed values. Say you have a boolean property whose initial state
259 is <TRUE/>. Say you call <member>notifyAndCachePropertyValue</member> the first time: it will
260 default construct the "old value" for this property as <FALSE/>, and thus <b>not</b> do
261 any notifications if the "current value" is also <FALSE/> - which might be wrong, since
262 the guessing of the "old value" differed from the real initial value which was <TRUE/>.
264 Too confusing? Okay, than just call this method for every property you have.
266 @param nHandle
267 the handle of the property. Must denote a property supported by this instance, i.e.
268 one previously registered via <member>registerProperty</member>.
269 @param rValue
270 the value to cache
271 @seealso notifyAndCachePropertyValue
273 void initializePropertyValueCache( sal_Int32 nHandle );
275 /// OPropertysetHelper methods
276 virtual sal_Bool SAL_CALL convertFastPropertyValue( Any_t& rConvertedValue, Any_t& rOldValue, sal_Int32 nHandle, const Any_t& rValue )
277 throw (::com::sun::star::lang::IllegalArgumentException);
278 virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any_t& rValue )
279 throw (::com::sun::star::uno::Exception);
280 virtual void SAL_CALL getFastPropertyValue( Any_t& rValue, sal_Int32 nHandle ) const;
282 virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
283 virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException);
285 public:
286 /// helper struct for granting selective access to some notification-related methods
287 struct NotifierAccess { friend struct PropertyChangeNotifier; private: NotifierAccess() { } };
288 /** retrieves the current property value for the given handle
289 @param nHandle
290 the handle of the property. Must denote a property supported by this instance, i.e.
291 one previously registered via <member>registerProperty</member>.
292 @see registerProperty
294 inline void getCurrentPropertyValueByHandle( sal_Int32 nHandle, Any_t& /* [out] */ rValue, const NotifierAccess& ) const
296 getFastPropertyValue( rValue, nHandle );
299 /** notifies a change in a given property to all interested listeners
301 inline void notifyPropertyChange( sal_Int32 nHandle, const Any_t& rOldValue, const Any_t& rNewValue, const NotifierAccess& ) const
303 const_cast< PropertySetBase* >( this )->firePropertyChange( nHandle, rNewValue, rOldValue );
306 using ::comphelper::OStatefulPropertySet::getFastPropertyValue;
308 private:
309 /** locates a property given by handle
310 @param nHandle
311 the handle of the property. Must denote a property supported by this instance, i.e.
312 one previously registered via <member>registerProperty</member>.
313 @see registerProperty
315 PropertyAccessorBase& locatePropertyHandler( sal_Int32 nHandle ) const;
318 /** a helper class for notifying property changes in a <type>PropertySetBase</type> instance.
320 You can create an instance of this class on the stack of a method which is to programmatically
321 change the value of a property. In its constructor, the instance will acquire the current property
322 value, and in its destructor, it will notify the change of this property's value (if necessary).
324 You do not need this class if you are modifying property values by using the X(Fast|Multi)PropertSet
325 methods, since those already care for property notifications. You only need it if you're changing
326 the internal representation of your property directly.
328 Also note that usually, notifications in the UNO world should be done without a locked mutex. So
329 if you use this class in conjunction with a <type>MutexGuard</type>, ensure that you <b>first</b>
330 instantiate the <type>PropertyChangeNotifier</type>, and <b>then</b> the <type>MutexGuard</type>,
331 so your mutex is released before the notification happens.
333 struct PropertyChangeNotifier
335 private:
336 const PropertySetBase& m_rPropertySet;
337 sal_Int32 m_nHandle;
338 com::sun::star::uno::Any m_aOldValue;
340 public:
341 /** constructs a PropertyChangeNotifier
342 @param rPropertySet
343 the property set implementation whose property is going to be changed. Note
344 that this property set implementation must live at least as long as the
345 PropertyChangeNotifier instance does.
346 @param nHandle
347 the handle of the property which is going to be changed. Must be a valid property
348 handle for the given <arg>rPropertySet</arg>
350 inline PropertyChangeNotifier( const PropertySetBase& rPropertySet, sal_Int32 nHandle )
351 :m_rPropertySet( rPropertySet )
352 ,m_nHandle( nHandle )
354 m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, m_aOldValue, PropertySetBase::NotifierAccess() );
356 inline ~PropertyChangeNotifier()
358 com::sun::star::uno::Any aNewValue;
359 m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, aNewValue, PropertySetBase::NotifierAccess() );
360 if ( aNewValue != m_aOldValue )
362 m_rPropertySet.notifyPropertyChange( m_nHandle, m_aOldValue, aNewValue, PropertySetBase::NotifierAccess() );
368 #define PROPERTY_FLAGS( NAME, TYPE, FLAG ) com::sun::star::beans::Property( \
369 ::rtl::OUString( #NAME, sizeof( #NAME ) - 1, RTL_TEXTENCODING_ASCII_US ), \
370 HANDLE_##NAME, getCppuType( static_cast< TYPE* >( NULL ) ), FLAG )
371 #define PROPERTY( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND )
372 #define PROPERTY_RO( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND | com::sun::star::beans::PropertyAttribute::READONLY )
374 #endif