12a97ec55SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
32a97ec55SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
42a97ec55SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
52a97ec55SAndrew Rist  * distributed with this work for additional information
62a97ec55SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
72a97ec55SAndrew Rist  * to you under the Apache License, Version 2.0 (the
82a97ec55SAndrew Rist  * "License"); you may not use this file except in compliance
92a97ec55SAndrew Rist  * with the License.  You may obtain a copy of the License at
102a97ec55SAndrew Rist  *
112a97ec55SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
122a97ec55SAndrew Rist  *
132a97ec55SAndrew Rist  * Unless required by applicable law or agreed to in writing,
142a97ec55SAndrew Rist  * software distributed under the License is distributed on an
152a97ec55SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162a97ec55SAndrew Rist  * KIND, either express or implied.  See the License for the
172a97ec55SAndrew Rist  * specific language governing permissions and limitations
182a97ec55SAndrew Rist  * under the License.
192a97ec55SAndrew Rist  *
202a97ec55SAndrew Rist  *************************************************************/
212a97ec55SAndrew Rist 
222a97ec55SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_extensions.hxx"
26cdf0e10cSrcweir #include "propertycomposer.hxx"
27cdf0e10cSrcweir 
28cdf0e10cSrcweir /** === begin UNO includes === **/
29cdf0e10cSrcweir #include <com/sun/star/lang/NullPointerException.hpp>
30cdf0e10cSrcweir #include <com/sun/star/lang/IllegalArgumentException.hpp>
31cdf0e10cSrcweir /** === end UNO includes === **/
32cdf0e10cSrcweir #include <osl/diagnose.h>
33cdf0e10cSrcweir #include <tools/diagnose_ex.h>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <functional>
36cdf0e10cSrcweir #include <algorithm>
37cdf0e10cSrcweir #include <map>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir //........................................................................
40cdf0e10cSrcweir namespace pcr
41cdf0e10cSrcweir {
42cdf0e10cSrcweir //........................................................................
43cdf0e10cSrcweir 
44cdf0e10cSrcweir     using namespace ::com::sun::star::uno;
45cdf0e10cSrcweir     using namespace ::com::sun::star::beans;
46cdf0e10cSrcweir     using namespace ::com::sun::star::lang;
47cdf0e10cSrcweir     using namespace ::com::sun::star::inspection;
48cdf0e10cSrcweir 
49cdf0e10cSrcweir 	//====================================================================
50cdf0e10cSrcweir 	//= helper
51cdf0e10cSrcweir 	//====================================================================
52cdf0e10cSrcweir     namespace
53cdf0e10cSrcweir     {
54cdf0e10cSrcweir         //----------------------------------------------------------------
55cdf0e10cSrcweir         struct SetPropertyValue : public ::std::unary_function< Reference< XPropertyHandler >, void >
56cdf0e10cSrcweir         {
57cdf0e10cSrcweir             ::rtl::OUString sPropertyName;
58cdf0e10cSrcweir             const Any&      rValue;
SetPropertyValuepcr::__anon95d7f75a0111::SetPropertyValue59cdf0e10cSrcweir             SetPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) : sPropertyName( _rPropertyName ), rValue( _rValue ) { }
operator ()pcr::__anon95d7f75a0111::SetPropertyValue60cdf0e10cSrcweir             void operator()( const Reference< XPropertyHandler >& _rHandler )
61cdf0e10cSrcweir             {
62cdf0e10cSrcweir                 _rHandler->setPropertyValue( sPropertyName, rValue );
63cdf0e10cSrcweir             }
64cdf0e10cSrcweir         };
65cdf0e10cSrcweir 
66cdf0e10cSrcweir         //----------------------------------------------------------------
67cdf0e10cSrcweir         template < class BagType >
putIntoBag(const Sequence<typename BagType::value_type> & _rArray,BagType & _rBag)68cdf0e10cSrcweir         void putIntoBag( const Sequence< typename BagType::value_type >& _rArray, BagType& /* [out] */ _rBag )
69cdf0e10cSrcweir         {
70cdf0e10cSrcweir             ::std::copy( _rArray.getConstArray(), _rArray.getConstArray() + _rArray.getLength(),
71cdf0e10cSrcweir                 ::std::insert_iterator< BagType >( _rBag, _rBag.begin() ) );
72cdf0e10cSrcweir         }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir         //----------------------------------------------------------------
75cdf0e10cSrcweir         template < class BagType >
copyBagToArray(const BagType & _rBag,Sequence<typename BagType::value_type> & _rArray)76cdf0e10cSrcweir         void copyBagToArray( const BagType& /* [out] */ _rBag, Sequence< typename BagType::value_type >& _rArray )
77cdf0e10cSrcweir         {
78cdf0e10cSrcweir             _rArray.realloc( _rBag.size() );
79cdf0e10cSrcweir             ::std::copy( _rBag.begin(), _rBag.end(), _rArray.getArray() );
80cdf0e10cSrcweir         }
81cdf0e10cSrcweir     }
82cdf0e10cSrcweir 
83cdf0e10cSrcweir     //====================================================================
84cdf0e10cSrcweir     //= PropertyComposer
85cdf0e10cSrcweir 	//====================================================================
86cdf0e10cSrcweir 
87cdf0e10cSrcweir     // TODO: there are various places where we determine the first handler in our array which
88cdf0e10cSrcweir     // supports a given property id. This is, at the moment, done with searching all handlers,
89cdf0e10cSrcweir     // which is O( n * k ) at worst (n being the number of handlers, k being the maximum number
90cdf0e10cSrcweir     // of supported properties per handler). Shouldn't we cache this? So that it is O( log k )?
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 	//--------------------------------------------------------------------
PropertyComposer(const::std::vector<Reference<XPropertyHandler>> & _rSlaveHandlers)93cdf0e10cSrcweir     PropertyComposer::PropertyComposer( const ::std::vector< Reference< XPropertyHandler > >& _rSlaveHandlers )
94cdf0e10cSrcweir         :PropertyComposer_Base          ( m_aMutex          )
95cdf0e10cSrcweir         ,m_aSlaveHandlers               ( _rSlaveHandlers   )
96cdf0e10cSrcweir         ,m_aPropertyListeners           ( m_aMutex          )
97cdf0e10cSrcweir         ,m_bSupportedPropertiesAreKnown ( false             )
98cdf0e10cSrcweir     {
99cdf0e10cSrcweir         if ( m_aSlaveHandlers.empty() )
100cdf0e10cSrcweir             throw IllegalArgumentException();
101cdf0e10cSrcweir 
102cdf0e10cSrcweir         osl_incrementInterlockedCount( &m_refCount );
103cdf0e10cSrcweir         {
104cdf0e10cSrcweir             Reference< XPropertyChangeListener > xMeMyselfAndI( this );
105cdf0e10cSrcweir             for (   HandlerArray::const_iterator loop = m_aSlaveHandlers.begin();
106cdf0e10cSrcweir                     loop != m_aSlaveHandlers.end();
107cdf0e10cSrcweir                     ++loop
108cdf0e10cSrcweir                 )
109cdf0e10cSrcweir             {
110cdf0e10cSrcweir                 if ( !loop->is() )
111cdf0e10cSrcweir                     throw NullPointerException();
112cdf0e10cSrcweir                 (*loop)->addPropertyChangeListener( xMeMyselfAndI );
113cdf0e10cSrcweir             }
114cdf0e10cSrcweir         }
115cdf0e10cSrcweir         osl_decrementInterlockedCount( &m_refCount );
116cdf0e10cSrcweir     }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir     //--------------------------------------------------------------------
inspect(const Reference<XInterface> & _rxIntrospectee)119cdf0e10cSrcweir     void SAL_CALL PropertyComposer::inspect( const Reference< XInterface >& _rxIntrospectee ) throw (RuntimeException, NullPointerException)
120cdf0e10cSrcweir     {
121cdf0e10cSrcweir         MethodGuard aGuard( *this );
122cdf0e10cSrcweir 
123cdf0e10cSrcweir         for ( HandlerArray::const_iterator loop = m_aSlaveHandlers.begin();
124cdf0e10cSrcweir               loop != m_aSlaveHandlers.end();
125cdf0e10cSrcweir               ++loop
126cdf0e10cSrcweir             )
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             (*loop)->inspect( _rxIntrospectee );
129cdf0e10cSrcweir         }
130cdf0e10cSrcweir     }
131cdf0e10cSrcweir 
132cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & _rPropertyName)133cdf0e10cSrcweir     Any SAL_CALL PropertyComposer::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         MethodGuard aGuard( *this );
136cdf0e10cSrcweir         return m_aSlaveHandlers[0]->getPropertyValue( _rPropertyName );
137cdf0e10cSrcweir     }
138cdf0e10cSrcweir 
139cdf0e10cSrcweir     //--------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rValue)140cdf0e10cSrcweir     void SAL_CALL PropertyComposer::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
141cdf0e10cSrcweir     {
142cdf0e10cSrcweir         MethodGuard aGuard( *this );
143cdf0e10cSrcweir         ::std::for_each( m_aSlaveHandlers.begin(), m_aSlaveHandlers.end(), SetPropertyValue( _rPropertyName, _rValue ) );
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     //--------------------------------------------------------------------
convertToPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rControlValue)147cdf0e10cSrcweir     Any SAL_CALL PropertyComposer::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
148cdf0e10cSrcweir     {
149cdf0e10cSrcweir         MethodGuard aGuard( *this );
150cdf0e10cSrcweir         return m_aSlaveHandlers[0]->convertToPropertyValue( _rPropertyName, _rControlValue );
151cdf0e10cSrcweir     }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir     //--------------------------------------------------------------------
convertToControlValue(const::rtl::OUString & _rPropertyName,const Any & _rPropertyValue,const Type & _rControlValueType)154cdf0e10cSrcweir     Any SAL_CALL PropertyComposer::convertToControlValue( const ::rtl::OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
155cdf0e10cSrcweir     {
156cdf0e10cSrcweir         MethodGuard aGuard( *this );
157cdf0e10cSrcweir         return m_aSlaveHandlers[0]->convertToControlValue( _rPropertyName, _rPropertyValue, _rControlValueType );
158cdf0e10cSrcweir     }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertyState(const::rtl::OUString & _rPropertyName)161cdf0e10cSrcweir     PropertyState SAL_CALL PropertyComposer::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir         MethodGuard aGuard( *this );
164cdf0e10cSrcweir 
165cdf0e10cSrcweir         // assume DIRECT for the moment. This will stay this way if *all* slaves
166cdf0e10cSrcweir         // tell the property has DIRECT state, and if *all* values equal
167cdf0e10cSrcweir         PropertyState eState = PropertyState_DIRECT_VALUE;
168cdf0e10cSrcweir 
169cdf0e10cSrcweir         // check the master state
170cdf0e10cSrcweir         Reference< XPropertyHandler > xPrimary( *m_aSlaveHandlers.begin() );
171cdf0e10cSrcweir         Any aPrimaryValue = xPrimary->getPropertyValue( _rPropertyName );
172cdf0e10cSrcweir         eState = xPrimary->getPropertyState( _rPropertyName );
173cdf0e10cSrcweir 
174cdf0e10cSrcweir         // loop through the secondary sets
175cdf0e10cSrcweir         PropertyState eSecondaryState = PropertyState_DIRECT_VALUE;
176cdf0e10cSrcweir         for ( HandlerArray::const_iterator loop = ( m_aSlaveHandlers.begin() + 1 );
177cdf0e10cSrcweir               loop != m_aSlaveHandlers.end();
178cdf0e10cSrcweir               ++loop
179cdf0e10cSrcweir             )
180cdf0e10cSrcweir         {
181cdf0e10cSrcweir             // the secondary state
182cdf0e10cSrcweir             eSecondaryState = (*loop)->getPropertyState( _rPropertyName );
183cdf0e10cSrcweir 
184cdf0e10cSrcweir             // the secondary value
185cdf0e10cSrcweir             Any aSecondaryValue( (*loop)->getPropertyValue( _rPropertyName ) );
186cdf0e10cSrcweir 
187cdf0e10cSrcweir             if  (   ( PropertyState_AMBIGUOUS_VALUE == eSecondaryState )    // secondary is ambiguous
188cdf0e10cSrcweir                 ||  ( aPrimaryValue != aSecondaryValue )                    // unequal values
189cdf0e10cSrcweir                 )
190cdf0e10cSrcweir             {
191cdf0e10cSrcweir                 eState = PropertyState_AMBIGUOUS_VALUE;
192cdf0e10cSrcweir                 break;
193cdf0e10cSrcweir             }
194cdf0e10cSrcweir         }
195cdf0e10cSrcweir 
196cdf0e10cSrcweir         return eState;
197cdf0e10cSrcweir     }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir     //--------------------------------------------------------------------
addPropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)200cdf0e10cSrcweir     void SAL_CALL PropertyComposer::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
201cdf0e10cSrcweir     {
202cdf0e10cSrcweir         MethodGuard aGuard( *this );
203cdf0e10cSrcweir         m_aPropertyListeners.addListener( _rxListener );
204cdf0e10cSrcweir     }
205cdf0e10cSrcweir 
206cdf0e10cSrcweir     //--------------------------------------------------------------------
removePropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)207cdf0e10cSrcweir     void SAL_CALL PropertyComposer::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
208cdf0e10cSrcweir     {
209cdf0e10cSrcweir         MethodGuard aGuard( *this );
210cdf0e10cSrcweir         m_aPropertyListeners.removeListener( _rxListener );
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir     //--------------------------------------------------------------------
getSupportedProperties()214cdf0e10cSrcweir     Sequence< Property > SAL_CALL PropertyComposer::getSupportedProperties() throw (RuntimeException)
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         MethodGuard aGuard( *this );
217cdf0e10cSrcweir 
218cdf0e10cSrcweir         if ( !m_bSupportedPropertiesAreKnown )
219cdf0e10cSrcweir         {
220cdf0e10cSrcweir             // we support a property if and only if all of our slaves support it
221cdf0e10cSrcweir 
222cdf0e10cSrcweir             // initially, use all the properties of an arbitrary handler (we take the first one)
223cdf0e10cSrcweir             putIntoBag( (*m_aSlaveHandlers.begin())->getSupportedProperties(), m_aSupportedProperties );
224cdf0e10cSrcweir 
225cdf0e10cSrcweir             // now intersect with the properties of *all* other handlers
226cdf0e10cSrcweir             for ( HandlerArray::const_iterator loop = ( m_aSlaveHandlers.begin() + 1 );
227cdf0e10cSrcweir                 loop != m_aSlaveHandlers.end();
228cdf0e10cSrcweir                 ++loop
229cdf0e10cSrcweir                 )
230cdf0e10cSrcweir             {
231cdf0e10cSrcweir                 // the properties supported by the current handler
232cdf0e10cSrcweir                 PropertyBag aThisRound;
233cdf0e10cSrcweir                 putIntoBag( (*loop)->getSupportedProperties(), aThisRound );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir                 // the intersection of those properties with all we already have
236cdf0e10cSrcweir                 PropertyBag aIntersection;
237cdf0e10cSrcweir                 ::std::set_intersection( aThisRound.begin(), aThisRound.end(), m_aSupportedProperties.begin(), m_aSupportedProperties.end(),
238cdf0e10cSrcweir                     ::std::insert_iterator< PropertyBag >( aIntersection, aIntersection.begin() ), PropertyLessByName() );
239cdf0e10cSrcweir 
240cdf0e10cSrcweir                 m_aSupportedProperties.swap( aIntersection );
241cdf0e10cSrcweir                 if ( m_aSupportedProperties.empty() )
242cdf0e10cSrcweir                     break;
243cdf0e10cSrcweir             }
244cdf0e10cSrcweir 
245cdf0e10cSrcweir             // remove those properties which are not composable
246cdf0e10cSrcweir             for (   PropertyBag::iterator check = m_aSupportedProperties.begin();
247cdf0e10cSrcweir                     check != m_aSupportedProperties.end();
248cdf0e10cSrcweir                 )
249cdf0e10cSrcweir             {
250cdf0e10cSrcweir                 sal_Bool bIsComposable = isComposable( check->Name );
251cdf0e10cSrcweir                 if ( !bIsComposable )
252cdf0e10cSrcweir                 {
253cdf0e10cSrcweir                     PropertyBag::iterator next = check; ++next;
254cdf0e10cSrcweir                     m_aSupportedProperties.erase( check );
255cdf0e10cSrcweir                     check = next;
256cdf0e10cSrcweir                 }
257cdf0e10cSrcweir                 else
258cdf0e10cSrcweir                     ++check;
259cdf0e10cSrcweir             }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir             m_bSupportedPropertiesAreKnown = true;
262cdf0e10cSrcweir         }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir         Sequence< Property > aSurvived;
265cdf0e10cSrcweir         copyBagToArray( m_aSupportedProperties, aSurvived );
266cdf0e10cSrcweir         return aSurvived;
267cdf0e10cSrcweir     }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     //--------------------------------------------------------------------
uniteStringArrays(const PropertyComposer::HandlerArray & _rHandlers,Sequence<::rtl::OUString> (SAL_CALL XPropertyHandler::* pGetter)(void),Sequence<::rtl::OUString> & _rUnion)270cdf0e10cSrcweir     void uniteStringArrays( const PropertyComposer::HandlerArray& _rHandlers, Sequence< ::rtl::OUString > (SAL_CALL XPropertyHandler::*pGetter)( void ),
271cdf0e10cSrcweir         Sequence< ::rtl::OUString >& /* [out] */ _rUnion )
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir         ::std::set< ::rtl::OUString > aUnitedBag;
274cdf0e10cSrcweir 
275cdf0e10cSrcweir         Sequence< ::rtl::OUString > aThisRound;
276cdf0e10cSrcweir         for ( PropertyComposer::HandlerArray::const_iterator loop = _rHandlers.begin();
277cdf0e10cSrcweir               loop != _rHandlers.end();
278cdf0e10cSrcweir               ++loop
279cdf0e10cSrcweir             )
280cdf0e10cSrcweir         {
281cdf0e10cSrcweir             aThisRound = (loop->get()->*pGetter)();
282cdf0e10cSrcweir             putIntoBag( aThisRound, aUnitedBag );
283cdf0e10cSrcweir         }
284cdf0e10cSrcweir 
285cdf0e10cSrcweir         copyBagToArray( aUnitedBag, _rUnion );
286cdf0e10cSrcweir     }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir     //--------------------------------------------------------------------
getSupersededProperties()289cdf0e10cSrcweir     Sequence< ::rtl::OUString > SAL_CALL PropertyComposer::getSupersededProperties( ) throw (RuntimeException)
290cdf0e10cSrcweir     {
291cdf0e10cSrcweir         MethodGuard aGuard( *this );
292cdf0e10cSrcweir 
293cdf0e10cSrcweir         // we supersede those properties which are superseded by at least one of our slaves
294cdf0e10cSrcweir         Sequence< ::rtl::OUString > aSuperseded;
295cdf0e10cSrcweir         uniteStringArrays( m_aSlaveHandlers, &XPropertyHandler::getSupersededProperties, aSuperseded );
296cdf0e10cSrcweir         return aSuperseded;
297cdf0e10cSrcweir     }
298cdf0e10cSrcweir 
299cdf0e10cSrcweir     //--------------------------------------------------------------------
getActuatingProperties()300cdf0e10cSrcweir     Sequence< ::rtl::OUString > SAL_CALL PropertyComposer::getActuatingProperties( ) throw (RuntimeException)
301cdf0e10cSrcweir     {
302cdf0e10cSrcweir         MethodGuard aGuard( *this );
303cdf0e10cSrcweir 
304cdf0e10cSrcweir         // we're interested in those properties which at least one handler wants to have
305cdf0e10cSrcweir         Sequence< ::rtl::OUString > aActuating;
306cdf0e10cSrcweir         uniteStringArrays( m_aSlaveHandlers, &XPropertyHandler::getActuatingProperties, aActuating );
307cdf0e10cSrcweir         return aActuating;
308cdf0e10cSrcweir     }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir     //--------------------------------------------------------------------
describePropertyLine(const::rtl::OUString & _rPropertyName,const Reference<XPropertyControlFactory> & _rxControlFactory)311cdf0e10cSrcweir     LineDescriptor SAL_CALL PropertyComposer::describePropertyLine( const ::rtl::OUString& _rPropertyName,
312cdf0e10cSrcweir         const Reference< XPropertyControlFactory >& _rxControlFactory )
313cdf0e10cSrcweir         throw (UnknownPropertyException, NullPointerException, RuntimeException)
314cdf0e10cSrcweir     {
315cdf0e10cSrcweir         MethodGuard aGuard( *this );
316cdf0e10cSrcweir         return m_aSlaveHandlers[0]->describePropertyLine( _rPropertyName, _rxControlFactory );
317cdf0e10cSrcweir     }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir     //--------------------------------------------------------------------
isComposable(const::rtl::OUString & _rPropertyName)320cdf0e10cSrcweir     ::sal_Bool SAL_CALL PropertyComposer::isComposable( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
321cdf0e10cSrcweir     {
322cdf0e10cSrcweir         MethodGuard aGuard( *this );
323cdf0e10cSrcweir         return m_aSlaveHandlers[0]->isComposable( _rPropertyName );
324cdf0e10cSrcweir     }
325cdf0e10cSrcweir 
326cdf0e10cSrcweir     //--------------------------------------------------------------------
onInteractivePropertySelection(const::rtl::OUString & _rPropertyName,sal_Bool _bPrimary,Any & _rData,const Reference<XObjectInspectorUI> & _rxInspectorUI)327cdf0e10cSrcweir     InteractiveSelectionResult SAL_CALL PropertyComposer::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool _bPrimary, Any& _rData, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
328cdf0e10cSrcweir     {
329cdf0e10cSrcweir         if ( !_rxInspectorUI.is() )
330cdf0e10cSrcweir             throw NullPointerException();
331cdf0e10cSrcweir 
332cdf0e10cSrcweir         MethodGuard aGuard( *this );
333cdf0e10cSrcweir 
334cdf0e10cSrcweir         impl_ensureUIRequestComposer( _rxInspectorUI );
335cdf0e10cSrcweir         ComposedUIAutoFireGuard aAutoFireGuard( *m_pUIRequestComposer );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir         // ask the first of the handlers
338cdf0e10cSrcweir         InteractiveSelectionResult eResult = (*m_aSlaveHandlers.begin())->onInteractivePropertySelection(
339cdf0e10cSrcweir                 _rPropertyName,
340cdf0e10cSrcweir                 _bPrimary,
341cdf0e10cSrcweir                 _rData,
342cdf0e10cSrcweir                 m_pUIRequestComposer->getUIForPropertyHandler( *m_aSlaveHandlers.begin() )
343cdf0e10cSrcweir             );
344cdf0e10cSrcweir 
345cdf0e10cSrcweir         switch ( eResult )
346cdf0e10cSrcweir         {
347cdf0e10cSrcweir         case InteractiveSelectionResult_Cancelled:
348cdf0e10cSrcweir             // fine
349cdf0e10cSrcweir             break;
350cdf0e10cSrcweir 
351cdf0e10cSrcweir         case InteractiveSelectionResult_Success:
352cdf0e10cSrcweir         case InteractiveSelectionResult_Pending:
353cdf0e10cSrcweir             OSL_ENSURE( false, "PropertyComposer::onInteractivePropertySelection: no chance to forward the new value to the other handlers!" );
354cdf0e10cSrcweir             // This means that we cannot know the new property value, which either has already been set
355cdf0e10cSrcweir             // at the first component ("Success"), or will be set later on once the asynchronous input
356cdf0e10cSrcweir             // is finished ("Pending"). So, we also cannot forward this new property value to the other
357cdf0e10cSrcweir             // handlers.
358cdf0e10cSrcweir             // We would need to be a listener at the property at the first component, but even this wouldn't
359cdf0e10cSrcweir             // be sufficient, since the property handler is free to change *any* property during a dedicated
360cdf0e10cSrcweir             // property UI.
361cdf0e10cSrcweir             eResult = InteractiveSelectionResult_Cancelled;
362cdf0e10cSrcweir             break;
363cdf0e10cSrcweir 
364cdf0e10cSrcweir         case InteractiveSelectionResult_ObtainedValue:
365cdf0e10cSrcweir             // OK. Our own caller will pass this as setPropertyValue, and we will then pass it to
366cdf0e10cSrcweir             // all slave handlers
367cdf0e10cSrcweir             break;
368cdf0e10cSrcweir 
369cdf0e10cSrcweir         default:
370cdf0e10cSrcweir             OSL_ENSURE( false, "OPropertyBrowserController::onInteractivePropertySelection: unknown result value!" );
371cdf0e10cSrcweir             break;
372cdf0e10cSrcweir         }
373cdf0e10cSrcweir 
374cdf0e10cSrcweir         return eResult;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_ensureUIRequestComposer(const Reference<XObjectInspectorUI> & _rxInspectorUI)378cdf0e10cSrcweir     void PropertyComposer::impl_ensureUIRequestComposer( const Reference< XObjectInspectorUI >& _rxInspectorUI )
379cdf0e10cSrcweir     {
380cdf0e10cSrcweir         OSL_ENSURE( !m_pUIRequestComposer.get() || m_pUIRequestComposer->getDelegatorUI().get() == _rxInspectorUI.get(),
381cdf0e10cSrcweir             "PropertyComposer::impl_ensureUIRequestComposer: somebody's changing the horse in the mid of the race!" );
382cdf0e10cSrcweir 
383cdf0e10cSrcweir         if ( !m_pUIRequestComposer.get() )
384cdf0e10cSrcweir             m_pUIRequestComposer.reset( new ComposedPropertyUIUpdate( _rxInspectorUI, this ) );
385cdf0e10cSrcweir     }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir     //--------------------------------------------------------------------
actuatingPropertyChanged(const::rtl::OUString & _rActuatingPropertyName,const Any & _rNewValue,const Any & _rOldValue,const Reference<XObjectInspectorUI> & _rxInspectorUI,sal_Bool _bFirstTimeInit)388cdf0e10cSrcweir     void SAL_CALL PropertyComposer::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (NullPointerException, RuntimeException)
389cdf0e10cSrcweir     {
390cdf0e10cSrcweir         if ( !_rxInspectorUI.is() )
391cdf0e10cSrcweir             throw NullPointerException();
392cdf0e10cSrcweir 
393cdf0e10cSrcweir         MethodGuard aGuard( *this );
394cdf0e10cSrcweir 
395cdf0e10cSrcweir         impl_ensureUIRequestComposer( _rxInspectorUI );
396cdf0e10cSrcweir         ComposedUIAutoFireGuard aAutoFireGuard( *m_pUIRequestComposer );
397cdf0e10cSrcweir 
398cdf0e10cSrcweir         // ask all handlers which expressed interest in this particular property, and "compose" their
399cdf0e10cSrcweir         // commands for the UIUpdater
400cdf0e10cSrcweir         for (   HandlerArray::const_iterator loop = m_aSlaveHandlers.begin();
401cdf0e10cSrcweir                 loop != m_aSlaveHandlers.end();
402cdf0e10cSrcweir                 ++loop
403cdf0e10cSrcweir             )
404cdf0e10cSrcweir         {
405cdf0e10cSrcweir             // TODO: make this cheaper (cache it?)
406cdf0e10cSrcweir             const StlSyntaxSequence< ::rtl::OUString > aThisHandlersActuatingProps = (*loop)->getActuatingProperties();
407cdf0e10cSrcweir             for (   StlSyntaxSequence< ::rtl::OUString >::const_iterator loopProps = aThisHandlersActuatingProps.begin();
408cdf0e10cSrcweir                     loopProps != aThisHandlersActuatingProps.end();
409cdf0e10cSrcweir                     ++loopProps
410cdf0e10cSrcweir                 )
411cdf0e10cSrcweir             {
412cdf0e10cSrcweir                 if ( *loopProps == _rActuatingPropertyName )
413cdf0e10cSrcweir                 {
414cdf0e10cSrcweir                     (*loop)->actuatingPropertyChanged( _rActuatingPropertyName, _rNewValue, _rOldValue,
415cdf0e10cSrcweir                         m_pUIRequestComposer->getUIForPropertyHandler( *loop ),
416cdf0e10cSrcweir                         _bFirstTimeInit );
417cdf0e10cSrcweir                     break;
418cdf0e10cSrcweir                 }
419cdf0e10cSrcweir             }
420cdf0e10cSrcweir         }
421cdf0e10cSrcweir     }
422cdf0e10cSrcweir 
423cdf0e10cSrcweir     //--------------------------------------------------------------------
IMPLEMENT_FORWARD_XCOMPONENT(PropertyComposer,PropertyComposer_Base)424cdf0e10cSrcweir     IMPLEMENT_FORWARD_XCOMPONENT( PropertyComposer, PropertyComposer_Base )
425cdf0e10cSrcweir 
426cdf0e10cSrcweir     //--------------------------------------------------------------------
427cdf0e10cSrcweir     void SAL_CALL PropertyComposer::disposing()
428cdf0e10cSrcweir     {
429cdf0e10cSrcweir         MethodGuard aGuard( *this );
430cdf0e10cSrcweir 
431cdf0e10cSrcweir         // dispose our slave handlers
432cdf0e10cSrcweir         for ( PropertyComposer::HandlerArray::const_iterator loop = m_aSlaveHandlers.begin();
433cdf0e10cSrcweir               loop != m_aSlaveHandlers.end();
434cdf0e10cSrcweir               ++loop
435cdf0e10cSrcweir             )
436cdf0e10cSrcweir         {
437cdf0e10cSrcweir             (*loop)->removePropertyChangeListener( this );
438cdf0e10cSrcweir             (*loop)->dispose();
439cdf0e10cSrcweir         }
440cdf0e10cSrcweir 
441cdf0e10cSrcweir         clearContainer( m_aSlaveHandlers );
442cdf0e10cSrcweir 
443cdf0e10cSrcweir         if ( m_pUIRequestComposer.get() )
444cdf0e10cSrcweir             m_pUIRequestComposer->dispose();
445*3d762826SHerbert Dürr         m_pUIRequestComposer.reset();
446cdf0e10cSrcweir     }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     //--------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)449cdf0e10cSrcweir     void SAL_CALL PropertyComposer::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException)
450cdf0e10cSrcweir     {
451cdf0e10cSrcweir         if ( !impl_isSupportedProperty_nothrow( evt.PropertyName ) )
452cdf0e10cSrcweir             // A slave handler might fire events for more properties than we support. Ignore those.
453cdf0e10cSrcweir             return;
454cdf0e10cSrcweir 
455cdf0e10cSrcweir         PropertyChangeEvent aTranslatedEvent( evt );
456cdf0e10cSrcweir         try
457cdf0e10cSrcweir         {
458cdf0e10cSrcweir             aTranslatedEvent.NewValue = getPropertyValue( evt.PropertyName );
459cdf0e10cSrcweir         }
460cdf0e10cSrcweir         catch( const Exception& )
461cdf0e10cSrcweir         {
462cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
463cdf0e10cSrcweir         }
464cdf0e10cSrcweir         m_aPropertyListeners.notify( aTranslatedEvent, &XPropertyChangeListener::propertyChange );
465cdf0e10cSrcweir     }
466cdf0e10cSrcweir 
467cdf0e10cSrcweir     //--------------------------------------------------------------------
disposing(const EventObject & Source)468cdf0e10cSrcweir     void SAL_CALL PropertyComposer::disposing( const EventObject& Source ) throw (RuntimeException)
469cdf0e10cSrcweir     {
470cdf0e10cSrcweir         MethodGuard aGuard( *this );
471cdf0e10cSrcweir         m_aPropertyListeners.disposing( Source );
472cdf0e10cSrcweir     }
473cdf0e10cSrcweir 
474cdf0e10cSrcweir     //--------------------------------------------------------------------
suspend(sal_Bool _bSuspend)475cdf0e10cSrcweir     sal_Bool SAL_CALL PropertyComposer::suspend( sal_Bool _bSuspend ) throw (RuntimeException)
476cdf0e10cSrcweir     {
477cdf0e10cSrcweir         MethodGuard aGuard( *this );
478cdf0e10cSrcweir         for ( PropertyComposer::HandlerArray::const_iterator loop = m_aSlaveHandlers.begin();
479cdf0e10cSrcweir               loop != m_aSlaveHandlers.end();
480cdf0e10cSrcweir               ++loop
481cdf0e10cSrcweir             )
482cdf0e10cSrcweir         {
483cdf0e10cSrcweir             if ( !(*loop)->suspend( _bSuspend ) )
484cdf0e10cSrcweir             {
485cdf0e10cSrcweir                 if ( _bSuspend && ( loop != m_aSlaveHandlers.begin() ) )
486cdf0e10cSrcweir                 {
487cdf0e10cSrcweir                     // if we tried to suspend, but one of the slave handlers vetoed,
488cdf0e10cSrcweir                     // re-activate the handlers which actually did *not* veto
489cdf0e10cSrcweir                     // the suspension
490cdf0e10cSrcweir                     do
491cdf0e10cSrcweir                     {
492cdf0e10cSrcweir                         --loop;
493cdf0e10cSrcweir                         (*loop)->suspend( sal_False );
494cdf0e10cSrcweir                     }
495cdf0e10cSrcweir                     while ( loop != m_aSlaveHandlers.begin() );
496cdf0e10cSrcweir                 }
497cdf0e10cSrcweir                 return false;
498cdf0e10cSrcweir             }
499cdf0e10cSrcweir         }
500cdf0e10cSrcweir         return true;
501cdf0e10cSrcweir     }
502cdf0e10cSrcweir 
503cdf0e10cSrcweir     //--------------------------------------------------------------------
hasPropertyByName(const::rtl::OUString & _rName)504cdf0e10cSrcweir     sal_Bool SAL_CALL PropertyComposer::hasPropertyByName( const ::rtl::OUString& _rName ) throw (RuntimeException)
505cdf0e10cSrcweir     {
506cdf0e10cSrcweir         return impl_isSupportedProperty_nothrow( _rName );
507cdf0e10cSrcweir     }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir //........................................................................
510cdf0e10cSrcweir } // namespace pcr
511cdf0e10cSrcweir //........................................................................
512cdf0e10cSrcweir 
513