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: formcellbinding.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_xmloff.hxx"
33 #include "formcellbinding.hxx"
34 #include <com/sun/star/form/binding/XBindableValue.hpp>
35 #include <com/sun/star/form/binding/XListEntrySink.hpp>
36 #include <com/sun/star/form/XGridColumnFactory.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/container/XNamed.hpp>
40 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
41 #include <com/sun/star/table/XCellRange.hpp>
42 #include <com/sun/star/form/XFormsSupplier.hpp>
43 #include <com/sun/star/form/XForm.hpp>
44 #include <com/sun/star/lang/XServiceInfo.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/beans/NamedValue.hpp>
47 #include "strings.hxx"
48 #include <osl/diagnose.h>
49 #include <rtl/logfile.hxx>
54 //............................................................................
57 //............................................................................
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::beans
;
61 using namespace ::com::sun::star::frame
;
62 using namespace ::com::sun::star::sheet
;
63 using namespace ::com::sun::star::container
;
64 using namespace ::com::sun::star::drawing
;
65 using namespace ::com::sun::star::table
;
66 using namespace ::com::sun::star::form
;
67 using namespace ::com::sun::star::lang
;
68 using namespace ::com::sun::star::form::binding
;
72 using ::com::sun::star::uno::Reference
;
73 using ::com::sun::star::uno::XInterface
;
74 using ::com::sun::star::container::XChild
;
75 using ::com::sun::star::frame::XModel
;
76 using ::com::sun::star::uno::UNO_QUERY
;
78 //....................................................................
79 template< class TYPE
>
80 Reference
< TYPE
> getTypedModelNode( const Reference
< XInterface
>& _rxModelNode
)
82 Reference
< TYPE
> xTypedNode( _rxModelNode
, UNO_QUERY
);
83 if ( xTypedNode
.is() )
87 Reference
< XChild
> xChild( _rxModelNode
, UNO_QUERY
);
89 return getTypedModelNode
< TYPE
>( xChild
->getParent() );
95 //....................................................................
96 Reference
< XModel
> getDocument( const Reference
< XInterface
>& _rxModelNode
)
98 return getTypedModelNode
< XModel
>( _rxModelNode
);
101 //....................................................................
102 struct StringCompare
: public ::std::unary_function
< ::rtl::OUString
, bool >
105 const ::rtl::OUString m_sReference
;
108 StringCompare( const ::rtl::OUString
& _rReference
) : m_sReference( _rReference
) { }
110 inline bool operator()( const ::rtl::OUString
& _rCompare
)
112 return ( _rCompare
== m_sReference
);
117 //========================================================================
118 //= FormCellBindingHelper
119 //========================================================================
120 //------------------------------------------------------------------------
121 FormCellBindingHelper::FormCellBindingHelper( const Reference
< XPropertySet
>& _rxControlModel
, const Reference
< XModel
>& _rxDocument
)
122 :m_xControlModel( _rxControlModel
)
123 ,m_xDocument( _rxDocument
, UNO_QUERY
)
125 OSL_ENSURE( m_xControlModel
.is(), "FormCellBindingHelper::FormCellBindingHelper: invalid control model!" );
127 if ( !m_xDocument
.is() )
128 m_xDocument
= m_xDocument
.query( getDocument( m_xControlModel
) );
129 OSL_ENSURE( m_xDocument
.is(), "FormCellBindingHelper::FormCellBindingHelper: Did not find the spreadsheet document!" );
132 //------------------------------------------------------------------------
133 sal_Bool
FormCellBindingHelper::livesInSpreadsheetDocument( const Reference
< XPropertySet
>& _rxControlModel
)
135 Reference
< XSpreadsheetDocument
> xDocument( getDocument( _rxControlModel
), UNO_QUERY
);
136 return xDocument
.is();
139 //------------------------------------------------------------------------
140 bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString
& _rAddressDescription
, CellAddress
& /* [out] */ _rAddress
, sal_Int16
/*_nAssumeSheet*/ ) const
143 return doConvertAddressRepresentations(
144 PROPERTY_FILE_REPRESENTATION
,
145 makeAny( _rAddressDescription
),
150 && ( aAddress
>>= _rAddress
);
153 //------------------------------------------------------------------------
154 bool FormCellBindingHelper::convertStringAddress( const ::rtl::OUString
& _rAddressDescription
,
155 CellRangeAddress
& /* [out] */ _rAddress
) const
158 return doConvertAddressRepresentations(
159 PROPERTY_FILE_REPRESENTATION
,
160 makeAny( _rAddressDescription
),
165 && ( aAddress
>>= _rAddress
);
168 //------------------------------------------------------------------------
169 Reference
< XValueBinding
> FormCellBindingHelper::createCellBindingFromStringAddress( const ::rtl::OUString
& _rAddress
, bool _bUseIntegerBinding
) const
171 Reference
< XValueBinding
> xBinding
;
172 if ( !m_xDocument
.is() )
176 // get the UNO representation of the address
177 CellAddress aAddress
;
178 if ( !_rAddress
.getLength() || !convertStringAddress( _rAddress
, aAddress
) )
181 xBinding
= xBinding
.query( createDocumentDependentInstance(
182 _bUseIntegerBinding
? SERVICE_LISTINDEXCELLBINDING
: SERVICE_CELLVALUEBINDING
,
190 //------------------------------------------------------------------------
191 Reference
< XListEntrySource
> FormCellBindingHelper::createCellListSourceFromStringAddress( const ::rtl::OUString
& _rAddress
) const
193 Reference
< XListEntrySource
> xSource
;
195 CellRangeAddress aRangeAddress
;
196 if ( !convertStringAddress( _rAddress
, aRangeAddress
) )
199 // create a range object for this address
200 xSource
= xSource
.query( createDocumentDependentInstance(
201 SERVICE_CELLRANGELISTSOURCE
,
202 PROPERTY_LIST_CELL_RANGE
,
203 makeAny( aRangeAddress
)
209 //------------------------------------------------------------------------
210 ::rtl::OUString
FormCellBindingHelper::getStringAddressFromCellBinding( const Reference
< XValueBinding
>& _rxBinding
) const
212 OSL_PRECOND( !_rxBinding
.is() || isCellBinding( _rxBinding
), "FormCellBindingHelper::getStringAddressFromCellBinding: this is no cell binding!" );
214 ::rtl::OUString sAddress
;
217 Reference
< XPropertySet
> xBindingProps( _rxBinding
, UNO_QUERY
);
218 OSL_ENSURE( xBindingProps
.is() || !_rxBinding
.is(), "FormCellBindingHelper::getStringAddressFromCellBinding: no property set for the binding!" );
219 if ( xBindingProps
.is() )
221 CellAddress aAddress
;
222 xBindingProps
->getPropertyValue( PROPERTY_BOUND_CELL
) >>= aAddress
;
225 doConvertAddressRepresentations( PROPERTY_ADDRESS
, makeAny( aAddress
),
226 PROPERTY_FILE_REPRESENTATION
, aStringAddress
, false );
228 aStringAddress
>>= sAddress
;
231 catch( const Exception
& )
233 OSL_ENSURE( sal_False
, "FormCellBindingHelper::getStringAddressFromCellBinding: caught an exception!" );
239 //------------------------------------------------------------------------
240 ::rtl::OUString
FormCellBindingHelper::getStringAddressFromCellListSource( const Reference
< XListEntrySource
>& _rxSource
) const
242 OSL_PRECOND( !_rxSource
.is() || isCellRangeListSource( _rxSource
), "FormCellBindingHelper::getStringAddressFromCellListSource: this is no cell list source!" );
244 ::rtl::OUString sAddress
;
247 Reference
< XPropertySet
> xSourceProps( _rxSource
, UNO_QUERY
);
248 OSL_ENSURE( xSourceProps
.is() || !_rxSource
.is(), "FormCellBindingHelper::getStringAddressFromCellListSource: no property set for the list source!" );
249 if ( xSourceProps
.is() )
251 CellRangeAddress aRangeAddress
;
252 xSourceProps
->getPropertyValue( PROPERTY_LIST_CELL_RANGE
) >>= aRangeAddress
;
255 doConvertAddressRepresentations( PROPERTY_ADDRESS
, makeAny( aRangeAddress
),
256 PROPERTY_FILE_REPRESENTATION
, aStringAddress
, true );
257 aStringAddress
>>= sAddress
;
260 catch( const Exception
& )
262 OSL_ENSURE( sal_False
, "FormCellBindingHelper::getStringAddressFromCellListSource: caught an exception!" );
268 //------------------------------------------------------------------------
269 bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const Reference
< XSpreadsheetDocument
>& _rxDocument
, const ::rtl::OUString
& _rService
) SAL_THROW(())
271 bool bYesItIs
= false;
275 Reference
< XServiceInfo
> xSI( _rxDocument
, UNO_QUERY
);
276 if ( xSI
.is() && xSI
->supportsService( SERVICE_SPREADSHEET_DOCUMENT
) )
278 Reference
< XMultiServiceFactory
> xDocumentFactory( _rxDocument
, UNO_QUERY
);
279 OSL_ENSURE( xDocumentFactory
.is(), "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: spreadsheet document, but no factory?" );
281 Sequence
< ::rtl::OUString
> aAvailableServices
;
282 if ( xDocumentFactory
.is() )
283 aAvailableServices
= xDocumentFactory
->getAvailableServiceNames( );
285 const ::rtl::OUString
* pFound
= ::std::find_if(
286 aAvailableServices
.getConstArray(),
287 aAvailableServices
.getConstArray() + aAvailableServices
.getLength(),
288 StringCompare( _rService
)
290 if ( pFound
- aAvailableServices
.getConstArray() < aAvailableServices
.getLength() )
296 catch( const Exception
& )
298 OSL_ENSURE( sal_False
, "FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies: caught an exception!" );
304 //------------------------------------------------------------------------
305 bool FormCellBindingHelper::isSpreadsheetDocumentWhichSupplies( const ::rtl::OUString
& _rService
) const SAL_THROW(())
307 return isSpreadsheetDocumentWhichSupplies( m_xDocument
, _rService
);
310 //------------------------------------------------------------------------
311 bool FormCellBindingHelper::isListCellRangeAllowed( const Reference
< XModel
>& _rxDocument
)
313 return isSpreadsheetDocumentWhichSupplies(
314 Reference
< XSpreadsheetDocument
>( _rxDocument
, UNO_QUERY
),
315 SERVICE_CELLRANGELISTSOURCE
319 //------------------------------------------------------------------------
320 bool FormCellBindingHelper::isListCellRangeAllowed( ) const
322 bool bAllow( false );
324 Reference
< XListEntrySink
> xSink( m_xControlModel
, UNO_QUERY
);
327 bAllow
= isSpreadsheetDocumentWhichSupplies( SERVICE_CELLRANGELISTSOURCE
);
333 //------------------------------------------------------------------------
334 bool FormCellBindingHelper::isCellBindingAllowed( ) const
336 bool bAllow( false );
338 Reference
< XBindableValue
> xBindable( m_xControlModel
, UNO_QUERY
);
339 if ( xBindable
.is() )
341 // the control can potentially be bound to an external value
342 // Does it live within a Calc document, and is able to supply CellBindings?
343 bAllow
= isSpreadsheetDocumentWhichSupplies( SERVICE_CELLVALUEBINDING
);
349 //------------------------------------------------------------------------
350 bool FormCellBindingHelper::isCellBindingAllowed( const Reference
< XModel
>& _rxDocument
)
352 return isSpreadsheetDocumentWhichSupplies(
353 Reference
< XSpreadsheetDocument
>( _rxDocument
, UNO_QUERY
),
354 SERVICE_CELLVALUEBINDING
358 //------------------------------------------------------------------------
359 bool FormCellBindingHelper::isCellBinding( const Reference
< XValueBinding
>& _rxBinding
) const
361 return doesComponentSupport( _rxBinding
.get(), SERVICE_CELLVALUEBINDING
);
364 //------------------------------------------------------------------------
365 bool FormCellBindingHelper::isCellIntegerBinding( const Reference
< XValueBinding
>& _rxBinding
) const
367 return doesComponentSupport( _rxBinding
.get(), SERVICE_LISTINDEXCELLBINDING
);
370 //------------------------------------------------------------------------
371 bool FormCellBindingHelper::isCellRangeListSource( const Reference
< XListEntrySource
>& _rxSource
) const
373 return doesComponentSupport( _rxSource
.get(), SERVICE_CELLRANGELISTSOURCE
);
376 //------------------------------------------------------------------------
377 bool FormCellBindingHelper::doesComponentSupport( const Reference
< XInterface
>& _rxComponent
, const ::rtl::OUString
& _rService
) const
380 Reference
< XServiceInfo
> xSI( _rxComponent
, UNO_QUERY
);
381 bDoes
= xSI
.is() && xSI
->supportsService( _rService
);
385 //------------------------------------------------------------------------
386 Reference
< XValueBinding
> FormCellBindingHelper::getCurrentBinding( ) const
388 Reference
< XValueBinding
> xBinding
;
389 Reference
< XBindableValue
> xBindable( m_xControlModel
, UNO_QUERY
);
390 if ( xBindable
.is() )
391 xBinding
= xBindable
->getValueBinding();
395 //------------------------------------------------------------------------
396 Reference
< XListEntrySource
> FormCellBindingHelper::getCurrentListSource( ) const
398 Reference
< XListEntrySource
> xSource
;
399 Reference
< XListEntrySink
> xSink( m_xControlModel
, UNO_QUERY
);
401 xSource
= xSink
->getListEntrySource();
405 //------------------------------------------------------------------------
406 void FormCellBindingHelper::setBinding( const Reference
< XValueBinding
>& _rxBinding
)
408 Reference
< XBindableValue
> xBindable( m_xControlModel
, UNO_QUERY
);
409 OSL_PRECOND( xBindable
.is(), "FormCellBindingHelper::setBinding: the object is not bindable!" );
410 if ( xBindable
.is() )
411 xBindable
->setValueBinding( _rxBinding
);
414 //------------------------------------------------------------------------
415 void FormCellBindingHelper::setListSource( const Reference
< XListEntrySource
>& _rxSource
)
417 Reference
< XListEntrySink
> xSink( m_xControlModel
, UNO_QUERY
);
418 OSL_PRECOND( xSink
.is(), "FormCellBindingHelper::setListSource: the object is no list entry sink!" );
420 xSink
->setListEntrySource( _rxSource
);
423 //------------------------------------------------------------------------
424 Reference
< XInterface
> FormCellBindingHelper::createDocumentDependentInstance( const ::rtl::OUString
& _rService
, const ::rtl::OUString
& _rArgumentName
,
425 const Any
& _rArgumentValue
) const
427 Reference
< XInterface
> xReturn
;
429 Reference
< XMultiServiceFactory
> xDocumentFactory( m_xDocument
, UNO_QUERY
);
430 OSL_ENSURE( xDocumentFactory
.is(), "FormCellBindingHelper::createDocumentDependentInstance: no document service factory!" );
431 if ( xDocumentFactory
.is() )
435 if ( _rArgumentName
.getLength() )
438 aArg
.Name
= _rArgumentName
;
439 aArg
.Value
= _rArgumentValue
;
441 Sequence
< Any
> aArgs( 1 );
444 xReturn
= xDocumentFactory
->createInstanceWithArguments( _rService
, aArgs
);
448 xReturn
= xDocumentFactory
->createInstance( _rService
);
451 catch ( const Exception
& )
453 OSL_ENSURE( sal_False
, "FormCellBindingHelper::createDocumentDependentInstance: could not create the binding at the document!" );
459 //------------------------------------------------------------------------
460 bool FormCellBindingHelper::doConvertAddressRepresentations( const ::rtl::OUString
& _rInputProperty
, const Any
& _rInputValue
,
461 const ::rtl::OUString
& _rOutputProperty
, Any
& _rOutputValue
, bool _bIsRange
) const SAL_THROW(())
463 bool bSuccess
= false;
465 Reference
< XPropertySet
> xConverter(
466 createDocumentDependentInstance(
467 _bIsRange
? SERVICE_RANGEADDRESS_CONVERSION
: SERVICE_ADDRESS_CONVERSION
,
473 OSL_ENSURE( xConverter
.is(), "FormCellBindingHelper::doConvertAddressRepresentations: could not get a converter service!" );
474 if ( xConverter
.is() )
478 xConverter
->setPropertyValue( _rInputProperty
, _rInputValue
);
479 _rOutputValue
= xConverter
->getPropertyValue( _rOutputProperty
);
482 catch( const Exception
& )
484 OSL_ENSURE( sal_False
, "FormCellBindingHelper::doConvertAddressRepresentations: caught an exception!" );
491 //............................................................................
492 } // namespace xmloff
493 //............................................................................