1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include "cellbindinghandler.hxx"
31 #include "formstrings.hxx"
32 #include "formmetadata.hxx"
33 #include "cellbindinghelper.hxx"
35 /** === begin UNO includes === **/
36 #include <com/sun/star/form/binding/XValueBinding.hpp>
37 #include <com/sun/star/table/CellAddress.hpp>
38 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
39 /** === end UNO includes === **/
40 #include <tools/debug.hxx>
42 //------------------------------------------------------------------------
43 extern "C" void SAL_CALL
createRegistryInfo_CellBindingPropertyHandler()
45 ::pcr::CellBindingPropertyHandler::registerImplementation();
48 //........................................................................
51 //........................................................................
53 using namespace ::com::sun::star::uno
;
54 using namespace ::com::sun::star::table
;
55 using namespace ::com::sun::star::lang
;
56 using namespace ::com::sun::star::beans
;
57 using namespace ::com::sun::star::script
;
58 using namespace ::com::sun::star::frame
;
59 using namespace ::com::sun::star::inspection
;
60 using namespace ::com::sun::star::form::binding
;
61 using namespace ::comphelper
;
63 //====================================================================
64 //= CellBindingPropertyHandler
65 //====================================================================
66 DBG_NAME( CellBindingPropertyHandler
)
67 //--------------------------------------------------------------------
68 CellBindingPropertyHandler::CellBindingPropertyHandler( const Reference
< XComponentContext
>& _rxContext
)
69 :CellBindingPropertyHandler_Base( _rxContext
)
70 ,m_pCellExchangeConverter( new DefaultEnumRepresentation( *m_pInfoService
, ::getCppuType( static_cast< sal_Int16
* >( NULL
) ), PROPERTY_ID_CELL_EXCHANGE_TYPE
) )
72 DBG_CTOR( CellBindingPropertyHandler
, NULL
);
75 //--------------------------------------------------------------------
76 ::rtl::OUString SAL_CALL
CellBindingPropertyHandler::getImplementationName_static( ) throw (RuntimeException
)
78 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.CellBindingPropertyHandler" ) );
81 //--------------------------------------------------------------------
82 Sequence
< ::rtl::OUString
> SAL_CALL
CellBindingPropertyHandler::getSupportedServiceNames_static( ) throw (RuntimeException
)
84 Sequence
< ::rtl::OUString
> aSupported( 1 );
85 aSupported
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.CellBindingPropertyHandler" ) );
89 //--------------------------------------------------------------------
90 void CellBindingPropertyHandler::onNewComponent()
92 PropertyHandlerComponent::onNewComponent();
94 Reference
< XModel
> xDocument( impl_getContextDocument_nothrow() );
95 DBG_ASSERT( xDocument
.is(), "CellBindingPropertyHandler::onNewComponent: no document!" );
96 if ( CellBindingHelper::isSpreadsheetDocument( xDocument
) )
97 m_pHelper
.reset( new CellBindingHelper( m_xComponent
, xDocument
) );
100 //--------------------------------------------------------------------
101 CellBindingPropertyHandler::~CellBindingPropertyHandler( )
103 DBG_DTOR( CellBindingPropertyHandler
, NULL
);
106 //--------------------------------------------------------------------
107 Sequence
< ::rtl::OUString
> SAL_CALL
CellBindingPropertyHandler::getActuatingProperties( ) throw (RuntimeException
)
109 Sequence
< ::rtl::OUString
> aInterestingProperties( 3 );
110 aInterestingProperties
[0] = PROPERTY_LIST_CELL_RANGE
;
111 aInterestingProperties
[1] = PROPERTY_BOUND_CELL
;
112 aInterestingProperties
[2] = PROPERTY_CONTROLSOURCE
;
113 return aInterestingProperties
;
116 //--------------------------------------------------------------------
117 void SAL_CALL
CellBindingPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString
& _rActuatingPropertyName
, const Any
& _rNewValue
, const Any
& /*_rOldValue*/, const Reference
< XObjectInspectorUI
>& _rxInspectorUI
, sal_Bool _bFirstTimeInit
) throw (NullPointerException
, RuntimeException
)
119 ::osl::MutexGuard
aGuard( m_aMutex
);
120 PropertyId
nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName
) );
121 OSL_PRECOND( m_pHelper
.get(), "CellBindingPropertyHandler::actuatingPropertyChanged: inconsistentcy!" );
122 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
124 OSL_PRECOND( _rxInspectorUI
.is(), "FormComponentPropertyHandler::actuatingPropertyChanged: no access to the UI!" );
125 if ( !_rxInspectorUI
.is() )
126 throw NullPointerException();
128 ::std::vector
< PropertyId
> aDependentProperties
;
130 switch ( nActuatingPropId
)
132 // ----- BoundCell -----
133 case PROPERTY_ID_BOUND_CELL
:
135 // the SQL-data-binding related properties need to be enabled if and only if
136 // there is *no* valid cell binding
137 Reference
< XValueBinding
> xBinding
;
138 _rNewValue
>>= xBinding
;
140 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_CELL_EXCHANGE_TYPE
) )
141 _rxInspectorUI
->enablePropertyUI( PROPERTY_CELL_EXCHANGE_TYPE
, xBinding
.is() );
142 if ( impl_componentHasProperty_throw( PROPERTY_CONTROLSOURCE
) )
143 _rxInspectorUI
->enablePropertyUI( PROPERTY_CONTROLSOURCE
, !xBinding
.is() );
145 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_FILTERPROPOSAL
) )
146 _rxInspectorUI
->enablePropertyUI( PROPERTY_FILTERPROPOSAL
, !xBinding
.is() );
147 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_EMPTY_IS_NULL
) )
148 _rxInspectorUI
->enablePropertyUI( PROPERTY_EMPTY_IS_NULL
, !xBinding
.is() );
150 aDependentProperties
.push_back( PROPERTY_ID_BOUNDCOLUMN
);
152 if ( !xBinding
.is() && m_pHelper
->getCurrentBinding().is() )
154 // ensure that the "transfer selection as" property is reset. Since we can't remember
155 // it at the object itself, but derive it from the binding only, we have to normalize
156 // it now that there *is* no binding anymore.
157 setPropertyValue( PROPERTY_CELL_EXCHANGE_TYPE
, makeAny( (sal_Int16
) 0 ) );
162 // ----- CellRange -----
163 case PROPERTY_ID_LIST_CELL_RANGE
:
165 // the list source related properties need to be enabled if and only if
166 // there is *no* valid external list source for the control
167 Reference
< XListEntrySource
> xSource
;
168 _rNewValue
>>= xSource
;
170 _rxInspectorUI
->enablePropertyUI( PROPERTY_STRINGITEMLIST
, !xSource
.is() );
171 _rxInspectorUI
->enablePropertyUI( PROPERTY_LISTSOURCE
, !xSource
.is() );
172 _rxInspectorUI
->enablePropertyUI( PROPERTY_LISTSOURCETYPE
, !xSource
.is() );
174 aDependentProperties
.push_back( PROPERTY_ID_BOUNDCOLUMN
);
176 // also reset the list entries if the cell range is reset
177 // #i28319# - 2004-04-27 - fs@openoffice.org
178 if ( !_bFirstTimeInit
)
183 setPropertyValue( PROPERTY_STRINGITEMLIST
, makeAny( Sequence
< ::rtl::OUString
>() ) );
185 catch( const Exception
& )
187 OSL_ENSURE( sal_False
, "OPropertyBrowserController::actuatingPropertyChanged( ListCellRange ): caught an exception while resetting the string items!" );
191 break; // case PROPERTY_ID_LIST_CELL_RANGE
193 // ----- DataField -----
194 case PROPERTY_ID_CONTROLSOURCE
:
196 ::rtl::OUString sControlSource
;
197 _rNewValue
>>= sControlSource
;
198 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_BOUND_CELL
) )
199 _rxInspectorUI
->enablePropertyUI( PROPERTY_BOUND_CELL
, sControlSource
.getLength() == 0 );
201 break; // case PROPERTY_ID_CONTROLSOURCE
204 DBG_ERROR( "CellBindingPropertyHandler::actuatingPropertyChanged: did not register for this property!" );
207 for ( ::std::vector
< PropertyId
>::const_iterator loopAffected
= aDependentProperties
.begin();
208 loopAffected
!= aDependentProperties
.end();
212 impl_updateDependentProperty_nothrow( *loopAffected
, _rxInspectorUI
);
216 //--------------------------------------------------------------------
217 void CellBindingPropertyHandler::impl_updateDependentProperty_nothrow( PropertyId _nPropId
, const Reference
< XObjectInspectorUI
>& _rxInspectorUI
) const
223 // ----- BoundColumn -----
224 case PROPERTY_ID_BOUNDCOLUMN
:
226 CellBindingPropertyHandler
* pNonConstThis
= const_cast< CellBindingPropertyHandler
* >( this );
227 Reference
< XValueBinding
> xBinding( pNonConstThis
->getPropertyValue( PROPERTY_BOUND_CELL
), UNO_QUERY
);
228 Reference
< XListEntrySource
> xListSource( pNonConstThis
->getPropertyValue( PROPERTY_LIST_CELL_RANGE
), UNO_QUERY
);
230 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_BOUNDCOLUMN
) )
231 _rxInspectorUI
->enablePropertyUI( PROPERTY_BOUNDCOLUMN
, !xBinding
.is() && !xListSource
.is() );
233 break; // case PROPERTY_ID_BOUNDCOLUMN
238 catch( const Exception
& )
240 OSL_ENSURE( sal_False
, "CellBindingPropertyHandler::impl_updateDependentProperty_nothrow: caught an exception!" );
244 //--------------------------------------------------------------------
245 Any SAL_CALL
CellBindingPropertyHandler::getPropertyValue( const ::rtl::OUString
& _rPropertyName
) throw (UnknownPropertyException
, RuntimeException
)
247 ::osl::MutexGuard
aGuard( m_aMutex
);
248 PropertyId
nPropId( impl_getPropertyId_throw( _rPropertyName
) );
250 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::getPropertyValue: inconsistency!" );
251 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
256 case PROPERTY_ID_BOUND_CELL
:
258 Reference
< XValueBinding
> xBinding( m_pHelper
->getCurrentBinding() );
259 if ( !m_pHelper
->isCellBinding( xBinding
) )
262 aReturn
<<= xBinding
;
266 case PROPERTY_ID_LIST_CELL_RANGE
:
268 Reference
< XListEntrySource
> xSource( m_pHelper
->getCurrentListSource() );
269 if ( !m_pHelper
->isCellRangeListSource( xSource
) )
276 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
278 Reference
< XValueBinding
> xBinding( m_pHelper
->getCurrentBinding() );
279 aReturn
<<= (sal_Int16
)( m_pHelper
->isCellIntegerBinding( xBinding
) ? 1 : 0 );
284 DBG_ERROR( "CellBindingPropertyHandler::getPropertyValue: cannot handle this!" );
290 //--------------------------------------------------------------------
291 void SAL_CALL
CellBindingPropertyHandler::setPropertyValue( const ::rtl::OUString
& _rPropertyName
, const Any
& _rValue
) throw (UnknownPropertyException
, RuntimeException
)
293 ::osl::MutexGuard
aGuard( m_aMutex
);
294 PropertyId
nPropId( impl_getPropertyId_throw( _rPropertyName
) );
296 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::setPropertyValue: inconsistency!" );
297 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
301 Any aOldValue
= getPropertyValue( _rPropertyName
);
305 case PROPERTY_ID_BOUND_CELL
:
307 Reference
< XValueBinding
> xBinding
;
308 _rValue
>>= xBinding
;
309 m_pHelper
->setBinding( xBinding
);
313 case PROPERTY_ID_LIST_CELL_RANGE
:
315 Reference
< XListEntrySource
> xSource
;
317 m_pHelper
->setListSource( xSource
);
321 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
323 sal_Int16 nExchangeType
= 0;
324 OSL_VERIFY( _rValue
>>= nExchangeType
);
326 Reference
< XValueBinding
> xBinding
= m_pHelper
->getCurrentBinding( );
329 sal_Bool bNeedIntegerBinding
= ( nExchangeType
== 1 );
330 if ( (bool)bNeedIntegerBinding
!= m_pHelper
->isCellIntegerBinding( xBinding
) )
332 CellAddress aAddress
;
333 if ( m_pHelper
->getAddressFromCellBinding( xBinding
, aAddress
) )
335 xBinding
= m_pHelper
->createCellBindingFromAddress( aAddress
, bNeedIntegerBinding
);
336 m_pHelper
->setBinding( xBinding
);
344 DBG_ERROR( "CellBindingPropertyHandler::setPropertyValue: cannot handle this!" );
348 impl_setContextDocumentModified_nothrow();
350 Any
aNewValue( getPropertyValue( _rPropertyName
) );
351 firePropertyChange( _rPropertyName
, nPropId
, aOldValue
, aNewValue
);
352 // TODO/UNOize: can't we make this a part of the base class, for all those "virtual"
353 // properties? Base class'es |setPropertyValue| could call some |doSetPropertyValue|,
354 // and handle the listener notification itself
356 catch( const Exception
& )
358 OSL_ENSURE( sal_False
, "CellBindingPropertyHandler::setPropertyValue: caught an exception!" );
362 //--------------------------------------------------------------------
363 Any SAL_CALL
CellBindingPropertyHandler::convertToPropertyValue( const ::rtl::OUString
& _rPropertyName
, const Any
& _rControlValue
) throw (UnknownPropertyException
, RuntimeException
)
365 ::osl::MutexGuard
aGuard( m_aMutex
);
368 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::convertToPropertyValue: we have no SupportedProperties!" );
369 if ( !m_pHelper
.get() )
370 return aPropertyValue
;
372 PropertyId
nPropId( m_pInfoService
->getPropertyId( _rPropertyName
) );
374 ::rtl::OUString sControlValue
;
375 OSL_VERIFY( _rControlValue
>>= sControlValue
);
378 case PROPERTY_ID_LIST_CELL_RANGE
:
379 aPropertyValue
<<= m_pHelper
->createCellListSourceFromStringAddress( sControlValue
);
382 case PROPERTY_ID_BOUND_CELL
:
384 // if we have the possibility of an integer binding, then we must preserve
385 // this property's value (e.g. if the current binding is an integer binding, then
386 // the newly created one must be, too)
387 bool bIntegerBinding
= false;
388 if ( m_pHelper
->isCellIntegerBindingAllowed() )
390 sal_Int16 nCurrentBindingType
= 0;
391 getPropertyValue( PROPERTY_CELL_EXCHANGE_TYPE
) >>= nCurrentBindingType
;
392 bIntegerBinding
= ( nCurrentBindingType
!= 0 );
394 aPropertyValue
<<= m_pHelper
->createCellBindingFromStringAddress( sControlValue
, bIntegerBinding
);
398 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
399 m_pCellExchangeConverter
->getValueFromDescription( sControlValue
, aPropertyValue
);
403 DBG_ERROR( "CellBindingPropertyHandler::convertToPropertyValue: cannot handle this!" );
407 return aPropertyValue
;
410 //--------------------------------------------------------------------
411 Any SAL_CALL
CellBindingPropertyHandler::convertToControlValue( const ::rtl::OUString
& _rPropertyName
,
412 const Any
& _rPropertyValue
, const Type
& /*_rControlValueType*/ ) throw (UnknownPropertyException
, RuntimeException
)
414 ::osl::MutexGuard
aGuard( m_aMutex
);
417 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::convertToControlValue: we have no SupportedProperties!" );
418 if ( !m_pHelper
.get() )
419 return aControlValue
;
421 PropertyId
nPropId( m_pInfoService
->getPropertyId( _rPropertyName
) );
425 case PROPERTY_ID_BOUND_CELL
:
427 Reference
< XValueBinding
> xBinding
;
428 #if OSL_DEBUG_LEVEL > 0
431 _rPropertyValue
>>= xBinding
;
432 OSL_ENSURE( bSuccess
, "CellBindingPropertyHandler::convertToControlValue: invalid value (1)!" );
434 // the only value binding we support so far is linking to spreadsheet cells
435 aControlValue
<<= m_pHelper
->getStringAddressFromCellBinding( xBinding
);
439 case PROPERTY_ID_LIST_CELL_RANGE
:
441 Reference
< XListEntrySource
> xSource
;
442 #if OSL_DEBUG_LEVEL > 0
445 _rPropertyValue
>>= xSource
;
446 OSL_ENSURE( bSuccess
, "CellBindingPropertyHandler::convertToControlValue: invalid value (2)!" );
448 // the only value binding we support so far is linking to spreadsheet cells
449 aControlValue
<<= m_pHelper
->getStringAddressFromCellListSource( xSource
);
453 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
454 aControlValue
<<= m_pCellExchangeConverter
->getDescriptionForValue( _rPropertyValue
);
458 DBG_ERROR( "CellBindingPropertyHandler::convertToControlValue: cannot handle this!" );
462 return aControlValue
;
465 //--------------------------------------------------------------------
466 Sequence
< Property
> SAL_CALL
CellBindingPropertyHandler::doDescribeSupportedProperties() const
468 ::std::vector
< Property
> aProperties
;
470 bool bAllowCellLinking
= m_pHelper
.get() && m_pHelper
->isCellBindingAllowed();
471 bool bAllowCellIntLinking
= m_pHelper
.get() && m_pHelper
->isCellIntegerBindingAllowed();
472 bool bAllowListCellRange
= m_pHelper
.get() && m_pHelper
->isListCellRangeAllowed();
473 if ( bAllowCellLinking
|| bAllowListCellRange
|| bAllowCellIntLinking
)
475 sal_Int32 nPos
= ( bAllowCellLinking
? 1 : 0 )
476 + ( bAllowListCellRange
? 1 : 0 )
477 + ( bAllowCellIntLinking
? 1 : 0 );
478 aProperties
.resize( nPos
);
480 if ( bAllowCellLinking
)
482 aProperties
[ --nPos
] = Property( PROPERTY_BOUND_CELL
, PROPERTY_ID_BOUND_CELL
,
483 ::getCppuType( static_cast< ::rtl::OUString
* >( NULL
) ), 0 );
485 if ( bAllowCellIntLinking
)
487 aProperties
[ --nPos
] = Property( PROPERTY_CELL_EXCHANGE_TYPE
, PROPERTY_ID_CELL_EXCHANGE_TYPE
,
488 ::getCppuType( static_cast< sal_Int16
* >( NULL
) ), 0 );
490 if ( bAllowListCellRange
)
492 aProperties
[ --nPos
] = Property( PROPERTY_LIST_CELL_RANGE
, PROPERTY_ID_LIST_CELL_RANGE
,
493 ::getCppuType( static_cast< ::rtl::OUString
* >( NULL
) ), 0 );
497 if ( aProperties
.empty() )
498 return Sequence
< Property
>();
499 return Sequence
< Property
>( &(*aProperties
.begin()), aProperties
.size() );
502 //........................................................................
504 //........................................................................