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 .
21 #include "propertyhandler.hxx"
22 #include "formmetadata.hxx"
23 #include "formbrowsertools.hxx"
24 #include "handlerhelper.hxx"
25 #include "formstrings.hxx"
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 <cppuhelper/supportsservice.hxx>
32 #include <tools/debug.hxx>
33 #include <unotools/confignode.hxx>
34 #include <unotools/localedatawrapper.hxx>
35 #include <unotools/syslocale.hxx>
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <rtl/ref.hxx>
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
;
55 PropertyHandler::PropertyHandler( const Reference
< XComponentContext
>& _rxContext
)
56 :PropertyHandler_Base( m_aMutex
)
57 ,m_bSupportedPropertiesAreKnown( false )
58 ,m_aPropertyListeners( m_aMutex
)
59 ,m_xContext( _rxContext
)
60 ,m_pInfoService ( new OPropertyInfoService
)
63 m_xTypeConverter
= Converter::create(_rxContext
);
66 PropertyHandler::~PropertyHandler()
70 void SAL_CALL
PropertyHandler::inspect( const Reference
< XInterface
>& _rxIntrospectee
)
72 if ( !_rxIntrospectee
.is() )
73 throw NullPointerException();
75 ::osl::MutexGuard
aGuard( m_aMutex
);
77 Reference
< XPropertySet
> xNewComponent( _rxIntrospectee
, UNO_QUERY
);
78 if ( xNewComponent
== m_xComponent
)
81 // remove all old property change listeners
82 ::comphelper::OInterfaceIteratorHelper3
removeListener(m_aPropertyListeners
);
83 ::comphelper::OInterfaceIteratorHelper3
readdListener(m_aPropertyListeners
); // will copy the container as needed
84 while ( removeListener
.hasMoreElements() )
85 removePropertyChangeListener( removeListener
.next() );
86 OSL_ENSURE( m_aPropertyListeners
.getLength() == 0, "PropertyHandler::inspect: derived classes are expected to forward the removePropertyChangeListener call to their base class (me)!" );
88 // remember the new component, and give derived classes the chance to react on it
89 m_xComponent
= xNewComponent
;
92 // add the listeners, again
93 while ( readdListener
.hasMoreElements() )
94 addPropertyChangeListener( readdListener
.next() );
97 void PropertyHandler::onNewComponent()
99 if ( m_xComponent
.is() )
100 m_xComponentPropertyInfo
= m_xComponent
->getPropertySetInfo();
102 m_xComponentPropertyInfo
.clear();
104 m_bSupportedPropertiesAreKnown
= false;
105 m_aSupportedProperties
.realloc( 0 );
108 Sequence
< Property
> SAL_CALL
PropertyHandler::getSupportedProperties()
110 ::osl::MutexGuard
aGuard( m_aMutex
);
111 if ( !m_bSupportedPropertiesAreKnown
)
113 m_aSupportedProperties
= StlSyntaxSequence
<css::beans::Property
>(doDescribeSupportedProperties());
114 m_bSupportedPropertiesAreKnown
= true;
116 return m_aSupportedProperties
;
119 Sequence
< OUString
> SAL_CALL
PropertyHandler::getSupersededProperties( )
121 return Sequence
< OUString
>();
124 Sequence
< OUString
> SAL_CALL
PropertyHandler::getActuatingProperties( )
126 return Sequence
< OUString
>();
129 Any SAL_CALL
PropertyHandler::convertToPropertyValue( const OUString
& _rPropertyName
, const Any
& _rControlValue
)
131 ::osl::MutexGuard
aGuard( m_aMutex
);
132 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
133 Property
aProperty( impl_getPropertyFromName_throw( _rPropertyName
) );
136 if ( !_rControlValue
.hasValue() )
137 // NULL is converted to NULL
138 return aPropertyValue
;
140 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
142 OUString sControlValue
;
143 OSL_VERIFY( _rControlValue
>>= sControlValue
);
144 ::rtl::Reference
< IPropertyEnumRepresentation
> aEnumConversion(
145 new DefaultEnumRepresentation( *m_pInfoService
, aProperty
.Type
, nPropId
) );
146 // TODO/UNOize: cache those converters?
147 aEnumConversion
->getValueFromDescription( sControlValue
, aPropertyValue
);
150 aPropertyValue
= PropertyHandlerHelper::convertToPropertyValue(
151 m_xContext
, m_xTypeConverter
, aProperty
, _rControlValue
);
152 return aPropertyValue
;
155 Any SAL_CALL
PropertyHandler::convertToControlValue( const OUString
& _rPropertyName
, const Any
& _rPropertyValue
, const Type
& _rControlValueType
)
157 ::osl::MutexGuard
aGuard( m_aMutex
);
158 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
160 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
162 DBG_ASSERT( _rControlValueType
.getTypeClass() == TypeClass_STRING
, "PropertyHandler::convertToControlValue: ENUM, but not STRING?" );
164 ::rtl::Reference
< IPropertyEnumRepresentation
> aEnumConversion(
165 new DefaultEnumRepresentation( *m_pInfoService
, _rPropertyValue
.getValueType(), nPropId
) );
166 // TODO/UNOize: cache those converters?
167 return Any( aEnumConversion
->getDescriptionForValue( _rPropertyValue
) );
170 return PropertyHandlerHelper::convertToControlValue(
171 m_xContext
, m_xTypeConverter
, _rPropertyValue
, _rControlValueType
);
174 PropertyState SAL_CALL
PropertyHandler::getPropertyState( const OUString
& /*_rPropertyName*/ )
176 return PropertyState_DIRECT_VALUE
;
179 LineDescriptor SAL_CALL
PropertyHandler::describePropertyLine( const OUString
& _rPropertyName
,
180 const Reference
< XPropertyControlFactory
>& _rxControlFactory
)
182 if ( !_rxControlFactory
.is() )
183 throw NullPointerException();
185 ::osl::MutexGuard
aGuard( m_aMutex
);
186 PropertyId
nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName
) );
187 const Property
& rProperty( impl_getPropertyFromId_throw( nPropId
) );
189 LineDescriptor aDescriptor
;
190 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_ENUM
) != 0 )
192 aDescriptor
.Control
= PropertyHandlerHelper::createListBoxControl(
193 _rxControlFactory
, m_pInfoService
->getPropertyEnumRepresentations( nPropId
),
194 PropertyHandlerHelper::requiresReadOnlyControl( rProperty
.Attributes
), false );
197 PropertyHandlerHelper::describePropertyLine( rProperty
, aDescriptor
, _rxControlFactory
);
199 aDescriptor
.HelpURL
= HelpIdUrl::getHelpURL( m_pInfoService
->getPropertyHelpId( nPropId
) );
200 aDescriptor
.DisplayName
= m_pInfoService
->getPropertyTranslation( nPropId
);
202 if ( ( m_pInfoService
->getPropertyUIFlags( nPropId
) & PROP_FLAG_DATA_PROPERTY
) != 0 )
203 aDescriptor
.Category
= "Data";
205 aDescriptor
.Category
= "General";
209 sal_Bool SAL_CALL
PropertyHandler::isComposable( const OUString
& _rPropertyName
)
211 ::osl::MutexGuard
aGuard( m_aMutex
);
212 return m_pInfoService
->isComposeable( _rPropertyName
);
215 InteractiveSelectionResult SAL_CALL
PropertyHandler::onInteractivePropertySelection( const OUString
& /*_rPropertyName*/, sal_Bool
/*_bPrimary*/, Any
& /*_rData*/, const Reference
< XObjectInspectorUI
>& /*_rxInspectorUI*/ )
217 OSL_FAIL( "PropertyHandler::onInteractivePropertySelection: not implemented!" );
218 return InteractiveSelectionResult_Cancelled
;
221 void SAL_CALL
PropertyHandler::actuatingPropertyChanged( const OUString
& /*_rActuatingPropertyName*/, const Any
& /*_rNewValue*/, const Any
& /*_rOldValue*/, const Reference
< XObjectInspectorUI
>& /*_rxInspectorUI*/, sal_Bool
/*_bFirstTimeInit*/ )
223 OSL_FAIL( "PropertyHandler::actuatingPropertyChanged: not implemented!" );
226 void SAL_CALL
PropertyHandler::addPropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
)
228 ::osl::MutexGuard
aGuard( m_aMutex
);
229 if ( !_rxListener
.is() )
230 throw NullPointerException();
231 m_aPropertyListeners
.addInterface( _rxListener
);
234 void SAL_CALL
PropertyHandler::removePropertyChangeListener( const Reference
< XPropertyChangeListener
>& _rxListener
)
236 ::osl::MutexGuard
aGuard( m_aMutex
);
237 m_aPropertyListeners
.removeInterface( _rxListener
);
240 sal_Bool SAL_CALL
PropertyHandler::suspend( sal_Bool
/*_bSuspend*/ )
245 void SAL_CALL
PropertyHandler::dispose( )
247 PropertyHandler_Base::WeakComponentImplHelperBase::dispose();
248 m_xComponent
.clear();
249 m_xComponentPropertyInfo
.clear();
250 m_xTypeConverter
.clear();
252 void SAL_CALL
PropertyHandler::addEventListener( const css::uno::Reference
< css::lang::XEventListener
>& Listener
)
254 PropertyHandler_Base::WeakComponentImplHelperBase::addEventListener( Listener
);
256 void SAL_CALL
PropertyHandler::removeEventListener( const css::uno::Reference
< css::lang::XEventListener
>& Listener
)
258 PropertyHandler_Base::WeakComponentImplHelperBase::removeEventListener( Listener
);
262 void SAL_CALL
PropertyHandler::disposing()
264 m_xComponent
.clear();
265 m_aPropertyListeners
.clear();
266 m_xTypeConverter
.clear();
267 m_aSupportedProperties
.realloc( 0 );
270 void PropertyHandler::firePropertyChange( const OUString
& _rPropName
, PropertyId _nPropId
, const Any
& _rOldValue
, const Any
& _rNewValue
)
272 PropertyChangeEvent aEvent
;
273 aEvent
.Source
= m_xComponent
;
274 aEvent
.PropertyHandle
= _nPropId
;
275 aEvent
.PropertyName
= _rPropName
;
276 aEvent
.OldValue
= _rOldValue
;
277 aEvent
.NewValue
= _rNewValue
;
278 m_aPropertyListeners
.notifyEach( &XPropertyChangeListener::propertyChange
, aEvent
);
281 const Property
* PropertyHandler::impl_getPropertyFromId_nothrow( PropertyId _nPropId
) const
283 const_cast< PropertyHandler
* >( this )->getSupportedProperties();
284 const Property
* pFound
= std::find_if( m_aSupportedProperties
.begin(), m_aSupportedProperties
.end(),
285 FindPropertyByHandle( _nPropId
)
287 if ( pFound
!= m_aSupportedProperties
.end() )
292 const Property
& PropertyHandler::impl_getPropertyFromId_throw( PropertyId _nPropId
) const
294 const Property
* pProperty
= impl_getPropertyFromId_nothrow( _nPropId
);
296 throw UnknownPropertyException();
301 const Property
& PropertyHandler::impl_getPropertyFromName_throw( const OUString
& _rPropertyName
) const
303 const_cast< PropertyHandler
* >( this )->getSupportedProperties();
304 StlSyntaxSequence
< Property
>::const_iterator pFound
= std::find_if( m_aSupportedProperties
.begin(), m_aSupportedProperties
.end(),
305 FindPropertyByName( _rPropertyName
)
307 if ( pFound
== m_aSupportedProperties
.end() )
308 throw UnknownPropertyException(_rPropertyName
);
313 void PropertyHandler::implAddPropertyDescription( std::vector
< Property
>& _rProperties
, const OUString
& _rPropertyName
, const Type
& _rType
, sal_Int16 _nAttribs
) const
315 _rProperties
.push_back( Property(
317 m_pInfoService
->getPropertyId( _rPropertyName
),
323 weld::Window
* PropertyHandler::impl_getDefaultDialogFrame_nothrow() const
325 return PropertyHandlerHelper::getDialogParentFrame(m_xContext
);
328 PropertyId
PropertyHandler::impl_getPropertyId_throwUnknownProperty( const OUString
& _rPropertyName
) const
330 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
332 throw UnknownPropertyException(_rPropertyName
);
336 PropertyId
PropertyHandler::impl_getPropertyId_throwRuntime( const OUString
& _rPropertyName
) const
338 PropertyId nPropId
= m_pInfoService
->getPropertyId( _rPropertyName
);
340 throw RuntimeException();
344 PropertyId
PropertyHandler::impl_getPropertyId_nothrow( const OUString
& _rPropertyName
) const
346 return m_pInfoService
->getPropertyId( _rPropertyName
);
349 void PropertyHandler::impl_setContextDocumentModified_nothrow() const
351 Reference
< XModifiable
> xModifiable( impl_getContextDocument_nothrow(), UNO_QUERY
);
352 if ( xModifiable
.is() )
353 xModifiable
->setModified( true );
356 bool PropertyHandler::impl_componentHasProperty_throw( const OUString
& _rPropName
) const
358 return m_xComponentPropertyInfo
.is() && m_xComponentPropertyInfo
->hasPropertyByName( _rPropName
);
361 sal_Int16
PropertyHandler::impl_getDocumentMeasurementUnit_throw() const
363 FieldUnit eUnit
= FieldUnit::NONE
;
365 Reference
< XServiceInfo
> xDocumentSI( impl_getContextDocument_nothrow(), UNO_QUERY
);
366 OSL_ENSURE( xDocumentSI
.is(), "PropertyHandlerHelper::impl_getDocumentMeasurementUnit_throw: No context document - where do I live?" );
367 if ( xDocumentSI
.is() )
369 // determine the application type we live in
370 OUString sConfigurationLocation
;
371 OUString sConfigurationProperty
;
372 if ( xDocumentSI
->supportsService( SERVICE_WEB_DOCUMENT
) )
374 sConfigurationLocation
= "/org.openoffice.Office.WriterWeb/Layout/Other";
375 sConfigurationProperty
= "MeasureUnit";
377 else if ( xDocumentSI
->supportsService( SERVICE_TEXT_DOCUMENT
) )
379 sConfigurationLocation
= "/org.openoffice.Office.Writer/Layout/Other";
380 sConfigurationProperty
= "MeasureUnit";
382 else if ( xDocumentSI
->supportsService( SERVICE_SPREADSHEET_DOCUMENT
) )
384 sConfigurationLocation
= "/org.openoffice.Office.Calc/Layout/Other/MeasureUnit";
385 sConfigurationProperty
= "Metric";
387 else if ( xDocumentSI
->supportsService( SERVICE_DRAWING_DOCUMENT
) )
389 sConfigurationLocation
= "/org.openoffice.Office.Draw/Layout/Other/MeasureUnit";
390 sConfigurationProperty
= "Metric";
392 else if ( xDocumentSI
->supportsService( SERVICE_PRESENTATION_DOCUMENT
) )
394 sConfigurationLocation
= "/org.openoffice.Office.Impress/Layout/Other/MeasureUnit";
395 sConfigurationProperty
= "Metric";
398 // read the measurement unit from the configuration
399 if ( !(sConfigurationLocation
.isEmpty() || sConfigurationProperty
.isEmpty()) )
401 ::utl::OConfigurationTreeRoot
aConfigTree( ::utl::OConfigurationTreeRoot::createWithComponentContext(
402 m_xContext
, sConfigurationLocation
, -1, ::utl::OConfigurationTreeRoot::CM_READONLY
) );
403 sal_Int32 nUnitAsInt
= sal_Int32(FieldUnit::NONE
);
404 aConfigTree
.getNodeValue( sConfigurationProperty
) >>= nUnitAsInt
;
406 // if this denotes a valid (and accepted) unit, then use it
407 if ( ( nUnitAsInt
> sal_Int32(FieldUnit::NONE
) ) && ( nUnitAsInt
<= sal_Int32(FieldUnit::MM_100TH
) ) )
408 eUnit
= static_cast< FieldUnit
>( nUnitAsInt
);
412 if ( FieldUnit::NONE
== eUnit
)
414 MeasurementSystem eSystem
= SvtSysLocale().GetLocaleData().getMeasurementSystemEnum();
415 eUnit
= MeasurementSystem::Metric
== eSystem
? FieldUnit::CM
: FieldUnit::INCH
;
418 return VCLUnoHelper::ConvertToMeasurementUnit( eUnit
, 1 );
421 PropertyHandlerComponent::PropertyHandlerComponent( const Reference
< XComponentContext
>& _rxContext
)
422 :PropertyHandler( _rxContext
)
426 IMPLEMENT_FORWARD_XINTERFACE2( PropertyHandlerComponent
, PropertyHandler
, PropertyHandlerComponent_Base
)
427 IMPLEMENT_FORWARD_XTYPEPROVIDER2( PropertyHandlerComponent
, PropertyHandler
, PropertyHandlerComponent_Base
)
429 sal_Bool SAL_CALL
PropertyHandlerComponent::supportsService( const OUString
& ServiceName
)
431 return cppu::supportsService(this, ServiceName
);
436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */