1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include "propertyhandler.hxx"
21 #include "formmetadata.hxx"
22 #include "formbrowsertools.hxx"
23 #include "handlerhelper.hxx"
24 #include "formstrings.hxx"
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <com/sun/star/lang/NullPointerException.hpp>
28 #include <com/sun/star/util/XModifiable.hpp>
29 #include <com/sun/star/script/Converter.hpp>
31 #include <tools/debug.hxx>
32 #include <unotools/confignode.hxx>
33 #include <unotools/localedatawrapper.hxx>
34 #include <unotools/syslocale.hxx>
35 #include <toolkit/helper/vclunohelper.hxx>
39 //........................................................................
42 //........................................................................
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::awt
;
46 using namespace ::com::sun::star::beans
;
47 using namespace ::com::sun::star::script
;
48 using namespace ::com::sun::star::lang
;
49 using namespace ::com::sun::star::util
;
50 using namespace ::com::sun::star::frame
;
51 using namespace ::com::sun::star::inspection
;
52 using namespace ::comphelper
;
54 //====================================================================
56 //====================================================================
57 DBG_NAME( PropertyHandler
)
58 //--------------------------------------------------------------------
59 PropertyHandler::PropertyHandler( const Reference
< XComponentContext
>& _rxContext
)
60 :PropertyHandler_Base( m_aMutex
)
61 ,m_bSupportedPropertiesAreKnown( false )
62 ,m_aPropertyListeners( m_aMutex
)
63 ,m_aContext( _rxContext
)
64 ,m_pInfoService ( new OPropertyInfoService
)
66 DBG_CTOR( PropertyHandler
, NULL
);
68 m_xTypeConverter
= Converter::create(_rxContext
);
71 //--------------------------------------------------------------------
72 PropertyHandler::~PropertyHandler()
74 DBG_DTOR( PropertyHandler
, NULL
);
77 //--------------------------------------------------------------------
78 void SAL_CALL
PropertyHandler::inspect( const Reference
< XInterface
>& _rxIntrospectee
) throw (RuntimeException
, NullPointerException
)
80 if ( !_rxIntrospectee
.is() )
81 throw NullPointerException();
83 ::osl::MutexGuard
aGuard( m_aMutex
);
85 Reference
< XPropertySet
> xNewComponent( _rxIntrospectee
, UNO_QUERY
);
86 if ( xNewComponent
== m_xComponent
)
89 // remove all old property change listeners
90 SAL_WNODEPRECATED_DECLARATIONS_PUSH
91 ::std::auto_ptr
< ::cppu::OInterfaceIteratorHelper
> removeListener
= m_aPropertyListeners
.createIterator();
92 ::std::auto_ptr
< ::cppu::OInterfaceIteratorHelper
> readdListener
= m_aPropertyListeners
.createIterator(); // will copy the container as needed
93 SAL_WNODEPRECATED_DECLARATIONS_POP
94 while ( removeListener
->hasMoreElements() )
95 removePropertyChangeListener( static_cast< XPropertyChangeListener
* >( removeListener
->next() ) );
96 OSL_ENSURE( m_aPropertyListeners
.empty(), "PropertyHandler::inspect: derived classes are expected to forward the removePropertyChangeListener call to their base class (me)!" );
98 // remember the new component, and give derived classes the chance to react on it
99 m_xComponent
= xNewComponent
;
102 // add the listeners, again
103 while ( readdListener
->hasMoreElements() )
104 addPropertyChangeListener( static_cast< XPropertyChangeListener
* >( readdListener
->next() ) );
107 //--------------------------------------------------------------------
108 void PropertyHandler::onNewComponent()
110 if ( m_xComponent
.is() )
111 m_xComponentPropertyInfo
= m_xComponent
->getPropertySetInfo();
113 m_xComponentPropertyInfo
.clear();
115 m_bSupportedPropertiesAreKnown
= false;
116 m_aSupportedProperties
.realloc( 0 );
119 //--------------------------------------------------------------------
120 Sequence
< Property
> SAL_CALL
PropertyHandler::getSupportedProperties() throw (RuntimeException
)
122 ::osl::MutexGuard
aGuard( m_aMutex
);
123 if ( !m_bSupportedPropertiesAreKnown
)
125 m_aSupportedProperties
= doDescribeSupportedProperties();
126 m_bSupportedPropertiesAreKnown
= true;
128 return (Sequence
< Property
>)m_aSupportedProperties
;
131 //--------------------------------------------------------------------
132 Sequence
< OUString
> SAL_CALL
PropertyHandler::getSupersededProperties( ) throw (RuntimeException
)
134 return Sequence
< OUString
>();
137 //--------------------------------------------------------------------
138 Sequence
< OUString
> SAL_CALL
PropertyHandler::getActuatingProperties( ) throw (RuntimeException
)
140 return Sequence
< OUString
>();
143 //--------------------------------------------------------------------
144 Any SAL_CALL
PropertyHandler::convertToPropertyValue( const OUString
& _rPropertyName
, const Any
& _rControlValue
) throw (UnknownPropertyException
, RuntimeException
)
146 ::osl::MutexGuard
aGuard( m_aMutex
);
147 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
148 Property
aProperty( impl_getPropertyFromName_throw( _rPropertyName
) );
151 if ( !_rControlValue
.hasValue() )
152 // NULL is converted to NULL
153 return aPropertyValue
;
155 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
157 OUString sControlValue
;
158 OSL_VERIFY( _rControlValue
>>= sControlValue
);
159 ::rtl::Reference
< IPropertyEnumRepresentation
> aEnumConversion(
160 new DefaultEnumRepresentation( *m_pInfoService
, aProperty
.Type
, nPropId
) );
161 // TODO/UNOize: cache those converters?
162 aEnumConversion
->getValueFromDescription( sControlValue
, aPropertyValue
);
165 aPropertyValue
= PropertyHandlerHelper::convertToPropertyValue(
166 m_aContext
.getContext(),m_xTypeConverter
, aProperty
, _rControlValue
);
167 return aPropertyValue
;
170 //--------------------------------------------------------------------
171 Any SAL_CALL
PropertyHandler::convertToControlValue( const OUString
& _rPropertyName
, const Any
& _rPropertyValue
, const Type
& _rControlValueType
) throw (UnknownPropertyException
, RuntimeException
)
173 ::osl::MutexGuard
aGuard( m_aMutex
);
174 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
176 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
178 DBG_ASSERT( _rControlValueType
.getTypeClass() == TypeClass_STRING
, "PropertyHandler::convertToControlValue: ENUM, but not STRING?" );
180 ::rtl::Reference
< IPropertyEnumRepresentation
> aEnumConversion(
181 new DefaultEnumRepresentation( *m_pInfoService
, _rPropertyValue
.getValueType(), nPropId
) );
182 // TODO/UNOize: cache those converters?
183 return makeAny( aEnumConversion
->getDescriptionForValue( _rPropertyValue
) );
186 return PropertyHandlerHelper::convertToControlValue(
187 m_aContext
.getContext(),m_xTypeConverter
, _rPropertyValue
, _rControlValueType
);
190 //--------------------------------------------------------------------
191 PropertyState SAL_CALL
PropertyHandler::getPropertyState( const OUString
& /*_rPropertyName*/ ) throw (UnknownPropertyException
, RuntimeException
)
193 return PropertyState_DIRECT_VALUE
;
196 //--------------------------------------------------------------------
197 LineDescriptor SAL_CALL
PropertyHandler::describePropertyLine( const OUString
& _rPropertyName
,
198 const Reference
< XPropertyControlFactory
>& _rxControlFactory
)
199 throw (UnknownPropertyException
, NullPointerException
, RuntimeException
)
201 if ( !_rxControlFactory
.is() )
202 throw NullPointerException();
204 ::osl::MutexGuard
aGuard( m_aMutex
);
205 PropertyId
nPropId( impl_getPropertyId_throw( _rPropertyName
) );
206 const Property
& rProperty( impl_getPropertyFromId_throw( nPropId
) );
208 LineDescriptor aDescriptor
;
209 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
211 aDescriptor
.Control
= PropertyHandlerHelper::createListBoxControl(
212 _rxControlFactory
, m_pInfoService
->getPropertyEnumRepresentations( nPropId
),
213 PropertyHandlerHelper::requiresReadOnlyControl( rProperty
.Attributes
), sal_False
);
216 PropertyHandlerHelper::describePropertyLine( rProperty
, aDescriptor
, _rxControlFactory
);
218 aDescriptor
.HelpURL
= HelpIdUrl::getHelpURL( m_pInfoService
->getPropertyHelpId( nPropId
) );
219 aDescriptor
.DisplayName
= m_pInfoService
->getPropertyTranslation( nPropId
);
221 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_DATA_PROPERTY
) != 0 )
222 aDescriptor
.Category
= OUString( "Data" );
224 aDescriptor
.Category
= OUString( "General" );
228 //--------------------------------------------------------------------
229 ::sal_Bool SAL_CALL
PropertyHandler::isComposable( const OUString
& _rPropertyName
) throw (UnknownPropertyException
, RuntimeException
)
231 ::osl::MutexGuard
aGuard( m_aMutex
);
232 return m_pInfoService
->isComposeable( _rPropertyName
);
235 //--------------------------------------------------------------------
236 InteractiveSelectionResult SAL_CALL
PropertyHandler::onInteractivePropertySelection( const OUString
& /*_rPropertyName*/, sal_Bool
/*_bPrimary*/, Any
& /*_rData*/, const Reference
< XObjectInspectorUI
>& /*_rxInspectorUI*/ ) throw (UnknownPropertyException
, NullPointerException
, RuntimeException
)
238 OSL_FAIL( "PropertyHandler::onInteractivePropertySelection: not implemented!" );
239 return InteractiveSelectionResult_Cancelled
;
242 //--------------------------------------------------------------------
243 void SAL_CALL
PropertyHandler::actuatingPropertyChanged( const OUString
& /*_rActuatingPropertyName*/, const Any
& /*_rNewValue*/, const Any
& /*_rOldValue*/, const Reference
< XObjectInspectorUI
>& /*_rxInspectorUI*/, sal_Bool
/*_bFirstTimeInit*/ ) throw (NullPointerException
, RuntimeException
)
245 OSL_FAIL( "PropertyHandler::actuatingPropertyChanged: not implemented!" );
248 //--------------------------------------------------------------------
249 void SAL_CALL
PropertyHandler::addPropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
) throw (RuntimeException
)
251 ::osl::MutexGuard
aGuard( m_aMutex
);
252 if ( !_rxListener
.is() )
253 throw NullPointerException();
254 m_aPropertyListeners
.addListener( _rxListener
);
257 //--------------------------------------------------------------------
258 void SAL_CALL
PropertyHandler::removePropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
) throw (RuntimeException
)
260 ::osl::MutexGuard
aGuard( m_aMutex
);
261 m_aPropertyListeners
.removeListener( _rxListener
);
264 //--------------------------------------------------------------------
265 sal_Bool SAL_CALL
PropertyHandler::suspend( sal_Bool
/*_bSuspend*/ ) throw (RuntimeException
)
270 //--------------------------------------------------------------------
271 IMPLEMENT_FORWARD_XCOMPONENT( PropertyHandler
, PropertyHandler_Base
)
272 //--------------------------------------------------------------------
273 void SAL_CALL
PropertyHandler::disposing()
275 m_xComponent
.clear();
276 m_aPropertyListeners
.clear();
277 m_xTypeConverter
.clear();
278 m_aSupportedProperties
.realloc( 0 );
281 //--------------------------------------------------------------------
282 void PropertyHandler::firePropertyChange( const OUString
& _rPropName
, PropertyId _nPropId
, const Any
& _rOldValue
, const Any
& _rNewValue
) SAL_THROW(())
284 PropertyChangeEvent aEvent
;
285 aEvent
.Source
= m_xComponent
;
286 aEvent
.PropertyHandle
= _nPropId
;
287 aEvent
.PropertyName
= _rPropName
;
288 aEvent
.OldValue
= _rOldValue
;
289 aEvent
.NewValue
= _rNewValue
;
290 m_aPropertyListeners
.notify( aEvent
, &XPropertyChangeListener::propertyChange
);
293 //--------------------------------------------------------------------
294 const Property
* PropertyHandler::impl_getPropertyFromId_nothrow( PropertyId _nPropId
) const
296 const_cast< PropertyHandler
* >( this )->getSupportedProperties();
297 const Property
* pFound
= ::std::find_if( m_aSupportedProperties
.begin(), m_aSupportedProperties
.end(),
298 FindPropertyByHandle( _nPropId
)
300 if ( pFound
!= m_aSupportedProperties
.end() )
305 //--------------------------------------------------------------------
306 const Property
& PropertyHandler::impl_getPropertyFromId_throw( PropertyId _nPropId
) const
308 const Property
* pProperty
= impl_getPropertyFromId_nothrow( _nPropId
);
310 throw UnknownPropertyException();
315 //--------------------------------------------------------------------
316 const Property
& PropertyHandler::impl_getPropertyFromName_throw( const OUString
& _rPropertyName
) const
318 const_cast< PropertyHandler
* >( this )->getSupportedProperties();
319 StlSyntaxSequence
< Property
>::const_iterator pFound
= ::std::find_if( m_aSupportedProperties
.begin(), m_aSupportedProperties
.end(),
320 FindPropertyByName( _rPropertyName
)
322 if ( pFound
== m_aSupportedProperties
.end() )
323 throw UnknownPropertyException();
328 //--------------------------------------------------------------------
329 void PropertyHandler::implAddPropertyDescription( ::std::vector
< Property
>& _rProperties
, const OUString
& _rPropertyName
, const Type
& _rType
, sal_Int16 _nAttribs
) const
331 _rProperties
.push_back( Property(
333 m_pInfoService
->getPropertyId( _rPropertyName
),
339 //------------------------------------------------------------------------
340 Window
* PropertyHandler::impl_getDefaultDialogParent_nothrow() const
342 return PropertyHandlerHelper::getDialogParentWindow( m_aContext
);
345 //------------------------------------------------------------------------
346 PropertyId
PropertyHandler::impl_getPropertyId_throw( const OUString
& _rPropertyName
) const
348 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
350 throw UnknownPropertyException();
354 //------------------------------------------------------------------------
355 void PropertyHandler::impl_setContextDocumentModified_nothrow() const
357 Reference
< XModifiable
> xModifiable( impl_getContextDocument_nothrow(), UNO_QUERY
);
358 if ( xModifiable
.is() )
359 xModifiable
->setModified( sal_True
);
362 //------------------------------------------------------------------------
363 bool PropertyHandler::impl_componentHasProperty_throw( const OUString
& _rPropName
) const
365 return m_xComponentPropertyInfo
.is() && m_xComponentPropertyInfo
->hasPropertyByName( _rPropName
);
368 //--------------------------------------------------------------------
369 sal_Int16
PropertyHandler::impl_getDocumentMeasurementUnit_throw() const
371 FieldUnit eUnit
= FUNIT_NONE
;
373 Reference
< XServiceInfo
> xDocumentSI( impl_getContextDocument_nothrow(), UNO_QUERY
);
374 OSL_ENSURE( xDocumentSI
.is(), "PropertyHandlerHelper::impl_getDocumentMeasurementUnit_throw: No context document - where do I live?" );
375 if ( xDocumentSI
.is() )
377 // determine the application type we live in
378 OUString sConfigurationLocation
;
379 OUString sConfigurationProperty
;
380 if ( xDocumentSI
->supportsService( SERVICE_WEB_DOCUMENT
) )
382 sConfigurationLocation
= OUString( "/org.openoffice.Office.WriterWeb/Layout/Other" );
383 sConfigurationProperty
= OUString( "MeasureUnit" );
385 else if ( xDocumentSI
->supportsService( SERVICE_TEXT_DOCUMENT
) )
387 sConfigurationLocation
= OUString( "/org.openoffice.Office.Writer/Layout/Other" );
388 sConfigurationProperty
= OUString( "MeasureUnit" );
390 else if ( xDocumentSI
->supportsService( SERVICE_SPREADSHEET_DOCUMENT
) )
392 sConfigurationLocation
= OUString( "/org.openoffice.Office.Calc/Layout/Other/MeasureUnit" );
393 sConfigurationProperty
= OUString( "Metric" );
395 else if ( xDocumentSI
->supportsService( SERVICE_DRAWING_DOCUMENT
) )
397 sConfigurationLocation
= OUString( "/org.openoffice.Office.Draw/Layout/Other/MeasureUnit" );
398 sConfigurationProperty
= OUString( "Metric" );
400 else if ( xDocumentSI
->supportsService( SERVICE_PRESENTATION_DOCUMENT
) )
402 sConfigurationLocation
= OUString( "/org.openoffice.Office.Impress/Layout/Other/MeasureUnit" );
403 sConfigurationProperty
= OUString( "Metric" );
406 // read the measurement unit from the configuration
407 if ( !(sConfigurationLocation
.isEmpty() || sConfigurationProperty
.isEmpty()) )
409 ::utl::OConfigurationTreeRoot
aConfigTree( ::utl::OConfigurationTreeRoot::createWithComponentContext(
410 m_aContext
.getUNOContext(), sConfigurationLocation
, -1, ::utl::OConfigurationTreeRoot::CM_READONLY
) );
411 sal_Int32 nUnitAsInt
= (sal_Int32
)FUNIT_NONE
;
412 aConfigTree
.getNodeValue( sConfigurationProperty
) >>= nUnitAsInt
;
414 // if this denotes a valid (and accepted) unit, then use it
415 if ( ( nUnitAsInt
> FUNIT_NONE
) && ( nUnitAsInt
<= FUNIT_100TH_MM
) )
416 eUnit
= static_cast< FieldUnit
>( nUnitAsInt
);
420 if ( FUNIT_NONE
== eUnit
)
422 MeasurementSystem eSystem
= SvtSysLocale().GetLocaleData().getMeasurementSystemEnum();
423 eUnit
= MEASURE_METRIC
== eSystem
? FUNIT_CM
: FUNIT_INCH
;
426 return VCLUnoHelper::ConvertToMeasurementUnit( eUnit
, 1 );
429 //====================================================================
430 //= PropertyHandlerComponent
431 //====================================================================
432 //------------------------------------------------------------------------
433 PropertyHandlerComponent::PropertyHandlerComponent( const Reference
< XComponentContext
>& _rxContext
)
434 :PropertyHandler( _rxContext
)
438 //--------------------------------------------------------------------
439 IMPLEMENT_FORWARD_XINTERFACE2( PropertyHandlerComponent
, PropertyHandler
, PropertyHandlerComponent_Base
)
440 IMPLEMENT_FORWARD_XTYPEPROVIDER2( PropertyHandlerComponent
, PropertyHandler
, PropertyHandlerComponent_Base
)
442 //--------------------------------------------------------------------
443 ::sal_Bool SAL_CALL
PropertyHandlerComponent::supportsService( const OUString
& ServiceName
) throw (RuntimeException
)
445 StlSyntaxSequence
< OUString
> aAllServices( getSupportedServiceNames() );
446 return ::std::find( aAllServices
.begin(), aAllServices
.end(), ServiceName
) != aAllServices
.end();
449 //........................................................................
451 //........................................................................
453 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */