1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cellbindinghandler.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
33 #include "cellbindinghandler.hxx"
34 #include "formstrings.hxx"
35 #include "formmetadata.hxx"
36 #include "cellbindinghelper.hxx"
38 /** === begin UNO includes === **/
39 #include <com/sun/star/form/binding/XValueBinding.hpp>
40 #include <com/sun/star/table/CellAddress.hpp>
41 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
42 /** === end UNO includes === **/
43 #include <tools/debug.hxx>
45 //------------------------------------------------------------------------
46 extern "C" void SAL_CALL
createRegistryInfo_CellBindingPropertyHandler()
48 ::pcr::CellBindingPropertyHandler::registerImplementation();
51 //........................................................................
54 //........................................................................
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::table
;
58 using namespace ::com::sun::star::lang
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::script
;
61 using namespace ::com::sun::star::frame
;
62 using namespace ::com::sun::star::inspection
;
63 using namespace ::com::sun::star::form::binding
;
64 using namespace ::comphelper
;
66 //====================================================================
67 //= CellBindingPropertyHandler
68 //====================================================================
69 DBG_NAME( CellBindingPropertyHandler
)
70 //--------------------------------------------------------------------
71 CellBindingPropertyHandler::CellBindingPropertyHandler( const Reference
< XComponentContext
>& _rxContext
)
72 :CellBindingPropertyHandler_Base( _rxContext
)
73 ,m_pCellExchangeConverter( new DefaultEnumRepresentation( *m_pInfoService
, ::getCppuType( static_cast< sal_Int16
* >( NULL
) ), PROPERTY_ID_CELL_EXCHANGE_TYPE
) )
75 DBG_CTOR( CellBindingPropertyHandler
, NULL
);
78 //--------------------------------------------------------------------
79 ::rtl::OUString SAL_CALL
CellBindingPropertyHandler::getImplementationName_static( ) throw (RuntimeException
)
81 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.CellBindingPropertyHandler" ) );
84 //--------------------------------------------------------------------
85 Sequence
< ::rtl::OUString
> SAL_CALL
CellBindingPropertyHandler::getSupportedServiceNames_static( ) throw (RuntimeException
)
87 Sequence
< ::rtl::OUString
> aSupported( 1 );
88 aSupported
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.CellBindingPropertyHandler" ) );
92 //--------------------------------------------------------------------
93 void CellBindingPropertyHandler::onNewComponent()
95 PropertyHandlerComponent::onNewComponent();
97 Reference
< XModel
> xDocument( impl_getContextDocument_nothrow() );
98 DBG_ASSERT( xDocument
.is(), "CellBindingPropertyHandler::onNewComponent: no document!" );
99 if ( CellBindingHelper::isSpreadsheetDocument( xDocument
) )
100 m_pHelper
.reset( new CellBindingHelper( m_xComponent
, xDocument
) );
103 //--------------------------------------------------------------------
104 CellBindingPropertyHandler::~CellBindingPropertyHandler( )
106 DBG_DTOR( CellBindingPropertyHandler
, NULL
);
109 //--------------------------------------------------------------------
110 Sequence
< ::rtl::OUString
> SAL_CALL
CellBindingPropertyHandler::getActuatingProperties( ) throw (RuntimeException
)
112 Sequence
< ::rtl::OUString
> aInterestingProperties( 3 );
113 aInterestingProperties
[0] = PROPERTY_LIST_CELL_RANGE
;
114 aInterestingProperties
[1] = PROPERTY_BOUND_CELL
;
115 aInterestingProperties
[2] = PROPERTY_CONTROLSOURCE
;
116 return aInterestingProperties
;
119 //--------------------------------------------------------------------
120 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
)
122 ::osl::MutexGuard
aGuard( m_aMutex
);
123 PropertyId
nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName
) );
124 OSL_PRECOND( m_pHelper
.get(), "CellBindingPropertyHandler::actuatingPropertyChanged: inconsistentcy!" );
125 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
127 OSL_PRECOND( _rxInspectorUI
.is(), "FormComponentPropertyHandler::actuatingPropertyChanged: no access to the UI!" );
128 if ( !_rxInspectorUI
.is() )
129 throw NullPointerException();
131 ::std::vector
< PropertyId
> aDependentProperties
;
133 switch ( nActuatingPropId
)
135 // ----- BoundCell -----
136 case PROPERTY_ID_BOUND_CELL
:
138 // the SQL-data-binding related properties need to be enabled if and only if
139 // there is *no* valid cell binding
140 Reference
< XValueBinding
> xBinding
;
141 _rNewValue
>>= xBinding
;
143 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_CELL_EXCHANGE_TYPE
) )
144 _rxInspectorUI
->enablePropertyUI( PROPERTY_CELL_EXCHANGE_TYPE
, xBinding
.is() );
145 if ( impl_componentHasProperty_throw( PROPERTY_CONTROLSOURCE
) )
146 _rxInspectorUI
->enablePropertyUI( PROPERTY_CONTROLSOURCE
, !xBinding
.is() );
148 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_FILTERPROPOSAL
) )
149 _rxInspectorUI
->enablePropertyUI( PROPERTY_FILTERPROPOSAL
, !xBinding
.is() );
150 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_EMPTY_IS_NULL
) )
151 _rxInspectorUI
->enablePropertyUI( PROPERTY_EMPTY_IS_NULL
, !xBinding
.is() );
153 aDependentProperties
.push_back( PROPERTY_ID_BOUNDCOLUMN
);
155 if ( !xBinding
.is() && m_pHelper
->getCurrentBinding().is() )
157 // ensure that the "transfer selection as" property is reset. Since we can't remember
158 // it at the object itself, but derive it from the binding only, we have to normalize
159 // it now that there *is* no binding anymore.
160 setPropertyValue( PROPERTY_CELL_EXCHANGE_TYPE
, makeAny( (sal_Int16
) 0 ) );
165 // ----- CellRange -----
166 case PROPERTY_ID_LIST_CELL_RANGE
:
168 // the list source related properties need to be enabled if and only if
169 // there is *no* valid external list source for the control
170 Reference
< XListEntrySource
> xSource
;
171 _rNewValue
>>= xSource
;
173 _rxInspectorUI
->enablePropertyUI( PROPERTY_STRINGITEMLIST
, !xSource
.is() );
174 _rxInspectorUI
->enablePropertyUI( PROPERTY_LISTSOURCE
, !xSource
.is() );
175 _rxInspectorUI
->enablePropertyUI( PROPERTY_LISTSOURCETYPE
, !xSource
.is() );
177 aDependentProperties
.push_back( PROPERTY_ID_BOUNDCOLUMN
);
179 // also reset the list entries if the cell range is reset
180 // #i28319# - 2004-04-27 - fs@openoffice.org
181 if ( !_bFirstTimeInit
)
186 setPropertyValue( PROPERTY_STRINGITEMLIST
, makeAny( Sequence
< ::rtl::OUString
>() ) );
188 catch( const Exception
& )
190 OSL_ENSURE( sal_False
, "OPropertyBrowserController::actuatingPropertyChanged( ListCellRange ): caught an exception while resetting the string items!" );
194 break; // case PROPERTY_ID_LIST_CELL_RANGE
196 // ----- DataField -----
197 case PROPERTY_ID_CONTROLSOURCE
:
199 ::rtl::OUString sControlSource
;
200 _rNewValue
>>= sControlSource
;
201 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_BOUND_CELL
) )
202 _rxInspectorUI
->enablePropertyUI( PROPERTY_BOUND_CELL
, sControlSource
.getLength() == 0 );
204 break; // case PROPERTY_ID_CONTROLSOURCE
207 DBG_ERROR( "CellBindingPropertyHandler::actuatingPropertyChanged: did not register for this property!" );
210 for ( ::std::vector
< PropertyId
>::const_iterator loopAffected
= aDependentProperties
.begin();
211 loopAffected
!= aDependentProperties
.end();
215 impl_updateDependentProperty_nothrow( *loopAffected
, _rxInspectorUI
);
219 //--------------------------------------------------------------------
220 void CellBindingPropertyHandler::impl_updateDependentProperty_nothrow( PropertyId _nPropId
, const Reference
< XObjectInspectorUI
>& _rxInspectorUI
) const
226 // ----- BoundColumn -----
227 case PROPERTY_ID_BOUNDCOLUMN
:
229 CellBindingPropertyHandler
* pNonConstThis
= const_cast< CellBindingPropertyHandler
* >( this );
230 Reference
< XValueBinding
> xBinding( pNonConstThis
->getPropertyValue( PROPERTY_BOUND_CELL
), UNO_QUERY
);
231 Reference
< XListEntrySource
> xListSource( pNonConstThis
->getPropertyValue( PROPERTY_LIST_CELL_RANGE
), UNO_QUERY
);
233 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_BOUNDCOLUMN
) )
234 _rxInspectorUI
->enablePropertyUI( PROPERTY_BOUNDCOLUMN
, !xBinding
.is() && !xListSource
.is() );
236 break; // case PROPERTY_ID_BOUNDCOLUMN
241 catch( const Exception
& )
243 OSL_ENSURE( sal_False
, "CellBindingPropertyHandler::impl_updateDependentProperty_nothrow: caught an exception!" );
247 //--------------------------------------------------------------------
248 Any SAL_CALL
CellBindingPropertyHandler::getPropertyValue( const ::rtl::OUString
& _rPropertyName
) throw (UnknownPropertyException
, RuntimeException
)
250 ::osl::MutexGuard
aGuard( m_aMutex
);
251 PropertyId
nPropId( impl_getPropertyId_throw( _rPropertyName
) );
253 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::getPropertyValue: inconsistency!" );
254 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
259 case PROPERTY_ID_BOUND_CELL
:
261 Reference
< XValueBinding
> xBinding( m_pHelper
->getCurrentBinding() );
262 if ( !m_pHelper
->isCellBinding( xBinding
) )
265 aReturn
<<= xBinding
;
269 case PROPERTY_ID_LIST_CELL_RANGE
:
271 Reference
< XListEntrySource
> xSource( m_pHelper
->getCurrentListSource() );
272 if ( !m_pHelper
->isCellRangeListSource( xSource
) )
279 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
281 Reference
< XValueBinding
> xBinding( m_pHelper
->getCurrentBinding() );
282 aReturn
<<= (sal_Int16
)( m_pHelper
->isCellIntegerBinding( xBinding
) ? 1 : 0 );
287 DBG_ERROR( "CellBindingPropertyHandler::getPropertyValue: cannot handle this!" );
293 //--------------------------------------------------------------------
294 void SAL_CALL
CellBindingPropertyHandler::setPropertyValue( const ::rtl::OUString
& _rPropertyName
, const Any
& _rValue
) throw (UnknownPropertyException
, RuntimeException
)
296 ::osl::MutexGuard
aGuard( m_aMutex
);
297 PropertyId
nPropId( impl_getPropertyId_throw( _rPropertyName
) );
299 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::setPropertyValue: inconsistency!" );
300 // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
304 Any aOldValue
= getPropertyValue( _rPropertyName
);
308 case PROPERTY_ID_BOUND_CELL
:
310 Reference
< XValueBinding
> xBinding
;
311 _rValue
>>= xBinding
;
312 m_pHelper
->setBinding( xBinding
);
316 case PROPERTY_ID_LIST_CELL_RANGE
:
318 Reference
< XListEntrySource
> xSource
;
320 m_pHelper
->setListSource( xSource
);
324 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
326 sal_Int16 nExchangeType
= 0;
327 OSL_VERIFY( _rValue
>>= nExchangeType
);
329 Reference
< XValueBinding
> xBinding
= m_pHelper
->getCurrentBinding( );
332 sal_Bool bNeedIntegerBinding
= ( nExchangeType
== 1 );
333 if ( (bool)bNeedIntegerBinding
!= m_pHelper
->isCellIntegerBinding( xBinding
) )
335 CellAddress aAddress
;
336 if ( m_pHelper
->getAddressFromCellBinding( xBinding
, aAddress
) )
338 xBinding
= m_pHelper
->createCellBindingFromAddress( aAddress
, bNeedIntegerBinding
);
339 m_pHelper
->setBinding( xBinding
);
347 DBG_ERROR( "CellBindingPropertyHandler::setPropertyValue: cannot handle this!" );
351 impl_setContextDocumentModified_nothrow();
353 Any
aNewValue( getPropertyValue( _rPropertyName
) );
354 firePropertyChange( _rPropertyName
, nPropId
, aOldValue
, aNewValue
);
355 // TODO/UNOize: can't we make this a part of the base class, for all those "virtual"
356 // properties? Base class'es |setPropertyValue| could call some |doSetPropertyValue|,
357 // and handle the listener notification itself
359 catch( const Exception
& )
361 OSL_ENSURE( sal_False
, "CellBindingPropertyHandler::setPropertyValue: caught an exception!" );
365 //--------------------------------------------------------------------
366 Any SAL_CALL
CellBindingPropertyHandler::convertToPropertyValue( const ::rtl::OUString
& _rPropertyName
, const Any
& _rControlValue
) throw (UnknownPropertyException
, RuntimeException
)
368 ::osl::MutexGuard
aGuard( m_aMutex
);
371 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::convertToPropertyValue: we have no SupportedProperties!" );
372 if ( !m_pHelper
.get() )
373 return aPropertyValue
;
375 PropertyId
nPropId( m_pInfoService
->getPropertyId( _rPropertyName
) );
377 ::rtl::OUString sControlValue
;
378 OSL_VERIFY( _rControlValue
>>= sControlValue
);
381 case PROPERTY_ID_LIST_CELL_RANGE
:
382 aPropertyValue
<<= m_pHelper
->createCellListSourceFromStringAddress( sControlValue
);
385 case PROPERTY_ID_BOUND_CELL
:
387 // if we have the possibility of an integer binding, then we must preserve
388 // this property's value (e.g. if the current binding is an integer binding, then
389 // the newly created one must be, too)
390 bool bIntegerBinding
= false;
391 if ( m_pHelper
->isCellIntegerBindingAllowed() )
393 sal_Int16 nCurrentBindingType
= 0;
394 getPropertyValue( PROPERTY_CELL_EXCHANGE_TYPE
) >>= nCurrentBindingType
;
395 bIntegerBinding
= ( nCurrentBindingType
!= 0 );
397 aPropertyValue
<<= m_pHelper
->createCellBindingFromStringAddress( sControlValue
, bIntegerBinding
);
401 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
402 m_pCellExchangeConverter
->getValueFromDescription( sControlValue
, aPropertyValue
);
406 DBG_ERROR( "CellBindingPropertyHandler::convertToPropertyValue: cannot handle this!" );
410 return aPropertyValue
;
413 //--------------------------------------------------------------------
414 Any SAL_CALL
CellBindingPropertyHandler::convertToControlValue( const ::rtl::OUString
& _rPropertyName
,
415 const Any
& _rPropertyValue
, const Type
& /*_rControlValueType*/ ) throw (UnknownPropertyException
, RuntimeException
)
417 ::osl::MutexGuard
aGuard( m_aMutex
);
420 OSL_ENSURE( m_pHelper
.get(), "CellBindingPropertyHandler::convertToControlValue: we have no SupportedProperties!" );
421 if ( !m_pHelper
.get() )
422 return aControlValue
;
424 PropertyId
nPropId( m_pInfoService
->getPropertyId( _rPropertyName
) );
428 case PROPERTY_ID_BOUND_CELL
:
430 Reference
< XValueBinding
> xBinding
;
431 #if OSL_DEBUG_LEVEL > 0
434 _rPropertyValue
>>= xBinding
;
435 OSL_ENSURE( bSuccess
, "CellBindingPropertyHandler::convertToControlValue: invalid value (1)!" );
437 // the only value binding we support so far is linking to spreadsheet cells
438 aControlValue
<<= m_pHelper
->getStringAddressFromCellBinding( xBinding
);
442 case PROPERTY_ID_LIST_CELL_RANGE
:
444 Reference
< XListEntrySource
> xSource
;
445 #if OSL_DEBUG_LEVEL > 0
448 _rPropertyValue
>>= xSource
;
449 OSL_ENSURE( bSuccess
, "CellBindingPropertyHandler::convertToControlValue: invalid value (2)!" );
451 // the only value binding we support so far is linking to spreadsheet cells
452 aControlValue
<<= m_pHelper
->getStringAddressFromCellListSource( xSource
);
456 case PROPERTY_ID_CELL_EXCHANGE_TYPE
:
457 aControlValue
<<= m_pCellExchangeConverter
->getDescriptionForValue( _rPropertyValue
);
461 DBG_ERROR( "CellBindingPropertyHandler::convertToControlValue: cannot handle this!" );
465 return aControlValue
;
468 //--------------------------------------------------------------------
469 Sequence
< Property
> SAL_CALL
CellBindingPropertyHandler::doDescribeSupportedProperties() const
471 ::std::vector
< Property
> aProperties
;
473 bool bAllowCellLinking
= m_pHelper
.get() && m_pHelper
->isCellBindingAllowed();
474 bool bAllowCellIntLinking
= m_pHelper
.get() && m_pHelper
->isCellIntegerBindingAllowed();
475 bool bAllowListCellRange
= m_pHelper
.get() && m_pHelper
->isListCellRangeAllowed();
476 if ( bAllowCellLinking
|| bAllowListCellRange
|| bAllowCellIntLinking
)
478 sal_Int32 nPos
= ( bAllowCellLinking
? 1 : 0 )
479 + ( bAllowListCellRange
? 1 : 0 )
480 + ( bAllowCellIntLinking
? 1 : 0 );
481 aProperties
.resize( nPos
);
483 if ( bAllowCellLinking
)
485 aProperties
[ --nPos
] = Property( PROPERTY_BOUND_CELL
, PROPERTY_ID_BOUND_CELL
,
486 ::getCppuType( static_cast< ::rtl::OUString
* >( NULL
) ), 0 );
488 if ( bAllowCellIntLinking
)
490 aProperties
[ --nPos
] = Property( PROPERTY_CELL_EXCHANGE_TYPE
, PROPERTY_ID_CELL_EXCHANGE_TYPE
,
491 ::getCppuType( static_cast< sal_Int16
* >( NULL
) ), 0 );
493 if ( bAllowListCellRange
)
495 aProperties
[ --nPos
] = Property( PROPERTY_LIST_CELL_RANGE
, PROPERTY_ID_LIST_CELL_RANGE
,
496 ::getCppuType( static_cast< ::rtl::OUString
* >( NULL
) ), 0 );
500 if ( aProperties
.empty() )
501 return Sequence
< Property
>();
502 return Sequence
< Property
>( &(*aProperties
.begin()), aProperties
.size() );
505 //........................................................................
507 //........................................................................