1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svx/shapepropertynotifier.hxx"
28 
29 /** === begin UNO includes === **/
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 /** === end UNO includes === **/
32 
33 #include <comphelper/stl_types.hxx>
34 #include <cppuhelper/interfacecontainer.hxx>
35 #include <cppuhelper/weak.hxx>
36 #include <tools/diagnose_ex.h>
37 
38 #include <hash_map>
39 
40 namespace
41 {
42 
43     struct ShapePropertyHash
44     {
operator ()__anon41dbe58d0111::ShapePropertyHash45         size_t operator()( ::svx::ShapeProperty __x ) const
46         {
47             return size_t( __x );
48         }
49     };
50 }
51 
52 //........................................................................
53 namespace svx
54 {
55 //........................................................................
56 
57 	/** === begin UNO using === **/
58 	using ::com::sun::star::uno::Reference;
59 	using ::com::sun::star::uno::XInterface;
60 	using ::com::sun::star::uno::UNO_QUERY;
61 	using ::com::sun::star::uno::UNO_QUERY_THROW;
62 	using ::com::sun::star::uno::UNO_SET_THROW;
63 	using ::com::sun::star::uno::Exception;
64 	using ::com::sun::star::uno::RuntimeException;
65 	using ::com::sun::star::uno::Any;
66 	using ::com::sun::star::uno::makeAny;
67 	using ::com::sun::star::uno::Sequence;
68 	using ::com::sun::star::uno::Type;
69     using ::com::sun::star::beans::PropertyChangeEvent;
70     using ::com::sun::star::beans::XPropertyChangeListener;
71     using ::com::sun::star::lang::EventObject;
72     using ::com::sun::star::beans::XPropertySet;
73 	/** === end UNO using === **/
74 
75     typedef ::std::hash_map< ShapeProperty, PPropertyValueProvider, ShapePropertyHash  >    PropertyProviders;
76 
77     typedef ::cppu::OMultiTypeInterfaceContainerHelperVar   <   ::rtl::OUString
78                                                             ,   ::comphelper::UStringHash
79                                                             ,   ::comphelper::UStringEqual
80                                                             >   PropertyChangeListenerContainer;
81 
82     //====================================================================
83 	//= IPropertyValueProvider
84 	//====================================================================
~IPropertyValueProvider()85     IPropertyValueProvider::~IPropertyValueProvider()
86     {
87     }
88 
89     //====================================================================
90 	//= PropertyChangeNotifier_Data
91 	//====================================================================
92     struct PropertyChangeNotifier_Data
93     {
94         ::cppu::OWeakObject&            m_rContext;
95         PropertyProviders               m_aProviders;
96         PropertyChangeListenerContainer m_aPropertyChangeListeners;
97 
PropertyChangeNotifier_Datasvx::PropertyChangeNotifier_Data98         PropertyChangeNotifier_Data( ::cppu::OWeakObject& _rContext, ::osl::Mutex& _rMutex )
99             :m_rContext( _rContext )
100             ,m_aPropertyChangeListeners( _rMutex )
101         {
102         }
103     };
104 	//====================================================================
105 	//= PropertyValueProvider
106 	//====================================================================
107 	//--------------------------------------------------------------------
getPropertyName() const108     ::rtl::OUString PropertyValueProvider::getPropertyName() const
109     {
110         return m_sPropertyName;
111     }
112 
113 	//--------------------------------------------------------------------
getCurrentValue(Any & _out_rValue) const114     void PropertyValueProvider::getCurrentValue( Any& _out_rValue ) const
115     {
116         Reference< XPropertySet > xContextProps( const_cast< PropertyValueProvider* >( this )->m_rContext, UNO_QUERY_THROW );
117         _out_rValue = xContextProps->getPropertyValue( getPropertyName() );
118     }
119 
120 	//====================================================================
121 	//= PropertyChangeNotifier
122 	//====================================================================
123 	//--------------------------------------------------------------------
PropertyChangeNotifier(::cppu::OWeakObject & _rOwner,::osl::Mutex & _rMutex)124     PropertyChangeNotifier::PropertyChangeNotifier( ::cppu::OWeakObject& _rOwner, ::osl::Mutex& _rMutex )
125         :m_pData( new PropertyChangeNotifier_Data( _rOwner, _rMutex ) )
126     {
127     }
128 
129 	//--------------------------------------------------------------------
~PropertyChangeNotifier()130     PropertyChangeNotifier::~PropertyChangeNotifier()
131     {
132     }
133 
134 	//--------------------------------------------------------------------
registerProvider(const ShapeProperty _eProperty,const PPropertyValueProvider _pProvider)135     void PropertyChangeNotifier::registerProvider( const ShapeProperty _eProperty, const PPropertyValueProvider _pProvider )
136     {
137         ENSURE_OR_THROW( _eProperty != eInvalidShapeProperty, "Illegal ShapeProperty value!" );
138         ENSURE_OR_THROW( !!_pProvider, "NULL factory not allowed." );
139 
140         OSL_ENSURE( m_pData->m_aProviders.find( _eProperty ) == m_pData->m_aProviders.end(),
141             "PropertyChangeNotifier::registerProvider: factory for this ID already present!" );
142 
143         m_pData->m_aProviders[ _eProperty ] = _pProvider;
144     }
145 
146 	//--------------------------------------------------------------------
notifyPropertyChange(const ShapeProperty _eProperty) const147     void PropertyChangeNotifier::notifyPropertyChange( const ShapeProperty _eProperty ) const
148     {
149         ENSURE_OR_THROW( _eProperty != eInvalidShapeProperty, "Illegal ShapeProperty value!" );
150 
151         PropertyProviders::const_iterator provPos = m_pData->m_aProviders.find( _eProperty );
152         OSL_ENSURE( provPos != m_pData->m_aProviders.end(), "PropertyChangeNotifier::notifyPropertyChange: no factory!" );
153         if ( provPos == m_pData->m_aProviders.end() )
154             return;
155 
156         ::rtl::OUString sPropertyName( provPos->second->getPropertyName() );
157 
158         ::cppu::OInterfaceContainerHelper* pPropListeners = m_pData->m_aPropertyChangeListeners.getContainer( sPropertyName );
159         ::cppu::OInterfaceContainerHelper* pAllListeners = m_pData->m_aPropertyChangeListeners.getContainer( ::rtl::OUString() );
160 	    if ( !pPropListeners && !pAllListeners )
161             return;
162 
163         try
164         {
165             PropertyChangeEvent aEvent;
166             aEvent.Source = m_pData->m_rContext;
167             // Handle/OldValue not supported
168             aEvent.PropertyName = provPos->second->getPropertyName();
169             provPos->second->getCurrentValue( aEvent.NewValue );
170 
171             if ( pPropListeners )
172                 pPropListeners->notifyEach( &XPropertyChangeListener::propertyChange, aEvent );
173             if ( pAllListeners )
174                 pAllListeners->notifyEach( &XPropertyChangeListener::propertyChange, aEvent );
175         }
176         catch( const Exception& )
177         {
178         	DBG_UNHANDLED_EXCEPTION();
179         }
180     }
181 
182 	//--------------------------------------------------------------------
addPropertyChangeListener(const::rtl::OUString & _rPropertyName,const Reference<XPropertyChangeListener> & _rxListener)183     void PropertyChangeNotifier::addPropertyChangeListener( const ::rtl::OUString& _rPropertyName, const Reference< XPropertyChangeListener >& _rxListener )
184     {
185         m_pData->m_aPropertyChangeListeners.addInterface( _rPropertyName, _rxListener );
186     }
187 
188 	//--------------------------------------------------------------------
removePropertyChangeListener(const::rtl::OUString & _rPropertyName,const Reference<XPropertyChangeListener> & _rxListener)189     void PropertyChangeNotifier::removePropertyChangeListener( const ::rtl::OUString& _rPropertyName, const Reference< XPropertyChangeListener >& _rxListener )
190     {
191         m_pData->m_aPropertyChangeListeners.removeInterface( _rPropertyName, _rxListener );
192     }
193 
194 	//--------------------------------------------------------------------
disposing()195     void PropertyChangeNotifier::disposing()
196     {
197         EventObject aEvent;
198         aEvent.Source = m_pData->m_rContext;
199         m_pData->m_aPropertyChangeListeners.disposeAndClear( aEvent );
200     }
201 
202 //........................................................................
203 } // namespace svx
204 //........................................................................
205