1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 #include "cellbindinghelper.hxx"
27 #include <com/sun/star/form/binding/XBindableValue.hpp>
28 #include <com/sun/star/form/binding/XListEntrySink.hpp>
29 #include <com/sun/star/form/FormComponentType.hpp>
30 #include <com/sun/star/form/XGridColumnFactory.hpp>
31 #include <com/sun/star/container/XChild.hpp>
32 #include <com/sun/star/container/XNamed.hpp>
33 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
34 #include <com/sun/star/table/XCellRange.hpp>
35 #include <com/sun/star/form/XFormsSupplier.hpp>
36 #include <com/sun/star/form/XForm.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/beans/NamedValue.hpp>
40 #include <com/sun/star/sheet/XSpreadsheet.hpp>
41 #include <unotools/transliterationwrapper.hxx>
42 #include <osl/diagnose.h>
43 #include <tools/diagnose_ex.h>
44 #include "formstrings.hxx"
45 
46 #include <functional>
47 #include <algorithm>
48 
49 //............................................................................
50 namespace pcr
51 {
52 //............................................................................
53 
54     using namespace ::com::sun::star::uno;
55     using namespace ::com::sun::star::beans;
56     using namespace ::com::sun::star::frame;
57     using namespace ::com::sun::star::sheet;
58     using namespace ::com::sun::star::container;
59     using namespace ::com::sun::star::drawing;
60     using namespace ::com::sun::star::table;
61     using namespace ::com::sun::star::form;
62     using namespace ::com::sun::star::lang;
63     using namespace ::com::sun::star::i18n;
64     using namespace ::com::sun::star::form::binding;
65 
66     namespace
67     {
68         //....................................................................
69         struct StringCompare : public ::std::unary_function< ::rtl::OUString, bool >
70         {
71         private:
72             ::rtl::OUString m_sReference;
73 
74         public:
StringComparepcr::__anon78523bd10111::StringCompare75             StringCompare( const ::rtl::OUString& _rReference ) : m_sReference( _rReference ) { }
76 
operator ()pcr::__anon78523bd10111::StringCompare77             inline bool operator()( const ::rtl::OUString& _rCompare )
78             {
79                 return ( _rCompare == m_sReference ) ? true : false;
80             }
81         };
82     }
83 
84     //========================================================================
85     //= CellBindingHelper
86     //========================================================================
87     //------------------------------------------------------------------------
CellBindingHelper(const Reference<XPropertySet> & _rxControlModel,const Reference<XModel> & _rxContextDocument)88     CellBindingHelper::CellBindingHelper( const Reference< XPropertySet >& _rxControlModel, const Reference< XModel >& _rxContextDocument )
89         :m_xControlModel( _rxControlModel )
90     {
91         OSL_ENSURE( m_xControlModel.is(), "CellBindingHelper::CellBindingHelper: invalid control model!" );
92 
93         m_xDocument = m_xDocument.query( _rxContextDocument );
94         OSL_ENSURE( m_xDocument.is(), "CellBindingHelper::CellBindingHelper: This is no spreadsheet document!" );
95 
96         OSL_ENSURE( isSpreadsheetDocumentWhichSupplies( SERVICE_ADDRESS_CONVERSION ),
97             "CellBindingHelper::CellBindingHelper: the document cannot convert address representations!" );
98     }
99 
100     //------------------------------------------------------------------------
isSpreadsheetDocument(const Reference<XModel> & _rxContextDocument)101     sal_Bool CellBindingHelper::isSpreadsheetDocument( const Reference< XModel >& _rxContextDocument )
102     {
103         return Reference< XSpreadsheetDocument >::query( _rxContextDocument ).is();
104     }
105 
106     //------------------------------------------------------------------------
getControlSheetIndex(Reference<XSpreadsheet> & _out_rxSheet) const107     sal_Int16 CellBindingHelper::getControlSheetIndex( Reference< XSpreadsheet >& _out_rxSheet ) const
108     {
109         sal_Int16 nSheetIndex = -1;
110         // every sheet has a draw page, and every draw page has a forms collection.
111         // Our control, OTOH, belongs to a forms collection. Match these ...
112         try
113         {
114             // for determining the draw page, we need the forms collection which
115             // the object belongs to. This is the first object up the hierarchy which is
116             // *no* XForm (and, well, no XGridColumnFactory)
117             Reference< XChild > xCheck( m_xControlModel, UNO_QUERY );
118             Reference< XForm > xParentAsForm; if ( xCheck.is() ) xParentAsForm = xParentAsForm.query( xCheck->getParent() );
119             Reference< XGridColumnFactory > xParentAsGrid; if ( xCheck.is() ) xParentAsGrid = xParentAsGrid.query( xCheck->getParent() );
120 
121             while ( ( xParentAsForm.is() || xParentAsGrid.is() ) && xCheck.is() )
122             {
123                 xCheck = xCheck.query( xCheck->getParent() );
124                 xParentAsForm = xParentAsForm.query( xCheck.is() ? xCheck->getParent() : (Reference< XInterface >) Reference< XForm >() );
125                 xParentAsGrid = xParentAsGrid.query( xCheck.is() ? xCheck->getParent() : (Reference< XInterface >) Reference< XGridColumnFactory >() );
126             }
127             Reference< XInterface > xFormsCollection( xCheck.is() ? xCheck->getParent() : Reference< XInterface >() );
128 
129             // now iterate through the sheets
130             Reference< XIndexAccess > xSheets( m_xDocument->getSheets(), UNO_QUERY );
131             if ( xSheets.is() && xFormsCollection.is() )
132             {
133                 for ( sal_Int32 i = 0; i < xSheets->getCount(); ++i )
134                 {
135                     Reference< XDrawPageSupplier > xSuppPage( xSheets->getByIndex( i ), UNO_QUERY_THROW );
136                     Reference< XFormsSupplier > xSuppForms( xSuppPage->getDrawPage(), UNO_QUERY_THROW );
137 
138                     if ( xSuppForms->getForms() == xFormsCollection )
139                     {   // found it
140                         nSheetIndex = (sal_Int16)i;
141                         _out_rxSheet.set( xSuppPage, UNO_QUERY_THROW );
142                         break;
143                     }
144                 }
145             }
146         }
147         catch( const Exception& )
148         {
149             DBG_UNHANDLED_EXCEPTION();
150         }
151 
152         return nSheetIndex;
153     }
154 
155     //------------------------------------------------------------------------
convertStringAddress(const::rtl::OUString & _rAddressDescription,CellAddress & _rAddress) const156     bool CellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription, CellAddress& /* [out] */ _rAddress ) const
157     {
158         Any aAddress;
159         return doConvertAddressRepresentations(
160                     PROPERTY_UI_REPRESENTATION,
161                     makeAny( _rAddressDescription ),
162                     PROPERTY_ADDRESS,
163                     aAddress,
164                     false
165                )
166            &&  ( aAddress >>= _rAddress );
167     }
168 
169     //------------------------------------------------------------------------
doConvertAddressRepresentations(const::rtl::OUString & _rInputProperty,const Any & _rInputValue,const::rtl::OUString & _rOutputProperty,Any & _rOutputValue,bool _bIsRange) const170     bool CellBindingHelper::doConvertAddressRepresentations( const ::rtl::OUString& _rInputProperty, const Any& _rInputValue,
171         const ::rtl::OUString& _rOutputProperty, Any& _rOutputValue, bool _bIsRange ) const SAL_THROW(())
172     {
173         bool bSuccess = false;
174 
175         Reference< XPropertySet > xConverter(
176             createDocumentDependentInstance(
177                 _bIsRange ? SERVICE_RANGEADDRESS_CONVERSION : SERVICE_ADDRESS_CONVERSION,
178                 ::rtl::OUString(),
179                 Any()
180             ),
181             UNO_QUERY
182         );
183         OSL_ENSURE( xConverter.is(), "CellBindingHelper::doConvertAddressRepresentations: could not get a converter service!" );
184         if ( xConverter.is() )
185         {
186             try
187             {
188                 Reference< XSpreadsheet > xSheet;
189                 xConverter->setPropertyValue( PROPERTY_REFERENCE_SHEET, makeAny( (sal_Int32)getControlSheetIndex( xSheet ) ) );
190                 xConverter->setPropertyValue( _rInputProperty, _rInputValue );
191                 _rOutputValue = xConverter->getPropertyValue( _rOutputProperty );
192                 bSuccess = true;
193             }
194             catch( const Exception& )
195             {
196             	OSL_ENSURE( sal_False, "CellBindingHelper::doConvertAddressRepresentations: caught an exception!" );
197             }
198         }
199 
200         return bSuccess;
201     }
202 
203     //------------------------------------------------------------------------
convertStringAddress(const::rtl::OUString & _rAddressDescription,CellRangeAddress & _rAddress) const204     bool CellBindingHelper::convertStringAddress( const ::rtl::OUString& _rAddressDescription,
205                             CellRangeAddress& /* [out] */ _rAddress ) const
206     {
207         Any aAddress;
208         return doConvertAddressRepresentations(
209                     PROPERTY_UI_REPRESENTATION,
210                     makeAny( _rAddressDescription ),
211                     PROPERTY_ADDRESS,
212                     aAddress,
213                     true
214                )
215            &&  ( aAddress >>= _rAddress );
216     }
217 
218     //------------------------------------------------------------------------
createCellBindingFromAddress(const CellAddress & _rAddress,bool _bSupportIntegerExchange) const219     Reference< XValueBinding > CellBindingHelper::createCellBindingFromAddress( const CellAddress& _rAddress, bool _bSupportIntegerExchange ) const
220     {
221         Reference< XValueBinding > xBinding( createDocumentDependentInstance(
222             _bSupportIntegerExchange ? SERVICE_SHEET_CELL_INT_BINDING : SERVICE_SHEET_CELL_BINDING,
223             PROPERTY_BOUND_CELL,
224             makeAny( _rAddress )
225         ), UNO_QUERY );
226 
227         return xBinding;
228     }
229 
230     //------------------------------------------------------------------------
createCellBindingFromStringAddress(const::rtl::OUString & _rAddress,bool _bSupportIntegerExchange) const231     Reference< XValueBinding > CellBindingHelper::createCellBindingFromStringAddress( const ::rtl::OUString& _rAddress, bool _bSupportIntegerExchange ) const
232     {
233         Reference< XValueBinding > xBinding;
234         if ( !m_xDocument.is() )
235             // very bad ...
236             return xBinding;
237 
238         // get the UNO representation of the address
239         CellAddress aAddress;
240         if ( !_rAddress.getLength() || !convertStringAddress( _rAddress, aAddress ) )
241             return xBinding;
242 
243         return createCellBindingFromAddress( aAddress, _bSupportIntegerExchange );
244     }
245 
246     //------------------------------------------------------------------------
createCellListSourceFromStringAddress(const::rtl::OUString & _rAddress) const247     Reference< XListEntrySource > CellBindingHelper::createCellListSourceFromStringAddress( const ::rtl::OUString& _rAddress ) const
248     {
249         Reference< XListEntrySource > xSource;
250 
251         CellRangeAddress aRangeAddress;
252         if ( !_rAddress.getLength() || !convertStringAddress( _rAddress, aRangeAddress ) )
253             return xSource;
254 
255         // create a range object for this address
256         xSource = xSource.query( createDocumentDependentInstance(
257             SERVICE_SHEET_CELLRANGE_LISTSOURCE,
258             PROPERTY_LIST_CELL_RANGE,
259             makeAny( aRangeAddress )
260         ) );
261 
262         return xSource;
263     }
264 
265     //------------------------------------------------------------------------
createDocumentDependentInstance(const::rtl::OUString & _rService,const::rtl::OUString & _rArgumentName,const Any & _rArgumentValue) const266     Reference< XInterface > CellBindingHelper::createDocumentDependentInstance( const ::rtl::OUString& _rService, const ::rtl::OUString& _rArgumentName,
267         const Any& _rArgumentValue ) const
268     {
269         Reference< XInterface > xReturn;
270 
271         Reference< XMultiServiceFactory > xDocumentFactory( m_xDocument, UNO_QUERY );
272         OSL_ENSURE( xDocumentFactory.is(), "CellBindingHelper::createDocumentDependentInstance: no document service factory!" );
273         if ( xDocumentFactory.is() )
274         {
275             try
276             {
277                 if ( _rArgumentName.getLength() )
278                 {
279                     NamedValue aArg;
280                     aArg.Name = _rArgumentName;
281                     aArg.Value = _rArgumentValue;
282 
283                     Sequence< Any > aArgs( 1 );
284                     aArgs[ 0 ] <<= aArg;
285 
286                     xReturn = xDocumentFactory->createInstanceWithArguments( _rService, aArgs );
287                 }
288                 else
289                 {
290                     xReturn = xDocumentFactory->createInstance( _rService );
291                 }
292             }
293             catch ( const Exception& )
294             {
295                 OSL_ENSURE( sal_False, "CellBindingHelper::createDocumentDependentInstance: could not create the binding at the document!" );
296             }
297         }
298         return xReturn;
299     }
300 
301     //------------------------------------------------------------------------
getAddressFromCellBinding(const Reference<XValueBinding> & _rxBinding,CellAddress & _rAddress) const302     bool CellBindingHelper::getAddressFromCellBinding(
303         const Reference< XValueBinding >& _rxBinding, CellAddress& _rAddress ) const
304     {
305         OSL_PRECOND( !_rxBinding.is() || isCellBinding( _rxBinding ), "CellBindingHelper::getAddressFromCellBinding: this is no cell binding!" );
306 
307         bool bReturn = false;
308         if ( !m_xDocument.is() )
309             // very bad ...
310             return bReturn;
311 
312         try
313         {
314             Reference< XPropertySet > xBindingProps( _rxBinding, UNO_QUERY );
315             OSL_ENSURE( xBindingProps.is() || !_rxBinding.is(), "CellBindingHelper::getAddressFromCellBinding: no property set for the binding!" );
316             if ( xBindingProps.is() )
317             {
318                 CellAddress aAddress;
319                 bReturn = (bool)( xBindingProps->getPropertyValue( PROPERTY_BOUND_CELL ) >>= _rAddress );
320             }
321         }
322         catch( const Exception& )
323         {
324             OSL_ENSURE( sal_False, "CellBindingHelper::getAddressFromCellBinding: caught an exception!" );
325         }
326 
327         return bReturn;
328     }
329 
330     //------------------------------------------------------------------------
getStringAddressFromCellBinding(const Reference<XValueBinding> & _rxBinding) const331     ::rtl::OUString CellBindingHelper::getStringAddressFromCellBinding( const Reference< XValueBinding >& _rxBinding ) const
332     {
333         CellAddress aAddress;
334         ::rtl::OUString sAddress;
335         if ( getAddressFromCellBinding( _rxBinding, aAddress ) )
336         {
337             Any aStringAddress;
338             doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aAddress ),
339                 PROPERTY_UI_REPRESENTATION, aStringAddress, false );
340 
341             aStringAddress >>= sAddress;
342         }
343 
344         return sAddress;
345     }
346 
347     //------------------------------------------------------------------------
getStringAddressFromCellListSource(const Reference<XListEntrySource> & _rxSource) const348     ::rtl::OUString CellBindingHelper::getStringAddressFromCellListSource( const Reference< XListEntrySource >& _rxSource ) const
349     {
350         OSL_PRECOND( !_rxSource.is() || isCellRangeListSource( _rxSource ), "CellBindingHelper::getStringAddressFromCellListSource: this is no cell list source!" );
351 
352         ::rtl::OUString sAddress;
353         if ( !m_xDocument.is() )
354             // very bad ...
355             return sAddress;
356 
357         try
358         {
359             Reference< XPropertySet > xSourceProps( _rxSource, UNO_QUERY );
360             OSL_ENSURE( xSourceProps.is() || !_rxSource.is(), "CellBindingHelper::getStringAddressFromCellListSource: no property set for the list source!" );
361             if ( xSourceProps.is() )
362             {
363                 CellRangeAddress aRangeAddress;
364                 xSourceProps->getPropertyValue( PROPERTY_LIST_CELL_RANGE ) >>= aRangeAddress;
365 
366                 Any aStringAddress;
367                 doConvertAddressRepresentations( PROPERTY_ADDRESS, makeAny( aRangeAddress ),
368                     PROPERTY_UI_REPRESENTATION, aStringAddress, true );
369                 aStringAddress >>= sAddress;
370             }
371         }
372         catch( const Exception& )
373         {
374             OSL_ENSURE( sal_False, "CellBindingHelper::getStringAddressFromCellListSource: caught an exception!" );
375         }
376 
377         return sAddress;
378     }
379 
380     //------------------------------------------------------------------------
isSpreadsheetDocumentWhichSupplies(const::rtl::OUString & _rService) const381     bool CellBindingHelper::isSpreadsheetDocumentWhichSupplies( const ::rtl::OUString& _rService ) const
382     {
383         bool bYesItIs = false;
384 
385         Reference< XServiceInfo > xSI( m_xDocument, UNO_QUERY );
386         if ( xSI.is() && xSI->supportsService( SERVICE_SPREADSHEET_DOCUMENT ) )
387         {
388             Reference< XMultiServiceFactory > xDocumentFactory( m_xDocument, UNO_QUERY );
389             OSL_ENSURE( xDocumentFactory.is(), "CellBindingHelper::isSpreadsheetDocumentWhichSupplies: spreadsheet document, but no factory?" );
390 
391             Sequence< ::rtl::OUString > aAvailableServices;
392             if ( xDocumentFactory.is() )
393                 aAvailableServices = xDocumentFactory->getAvailableServiceNames( );
394 
395             const ::rtl::OUString* pFound = ::std::find_if(
396                 aAvailableServices.getConstArray(),
397                 aAvailableServices.getConstArray() + aAvailableServices.getLength(),
398                 StringCompare( _rService )
399             );
400             if ( pFound - aAvailableServices.getConstArray() < aAvailableServices.getLength() )
401             {
402                 bYesItIs = true;
403             }
404         }
405 
406         return bYesItIs;
407     }
408 
409     //------------------------------------------------------------------------
isListCellRangeAllowed() const410     bool CellBindingHelper::isListCellRangeAllowed( ) const
411     {
412         bool bAllow( false );
413 
414         Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY );
415         if ( xSink.is() )
416         {
417             bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_SHEET_CELLRANGE_LISTSOURCE );
418         }
419 
420         return bAllow;
421     }
422 
423     //------------------------------------------------------------------------
isCellIntegerBindingAllowed() const424     bool CellBindingHelper::isCellIntegerBindingAllowed( ) const
425     {
426         bool bAllow( true );
427 
428         // first, we only offer this for controls which allow bindings in general
429         Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY );
430         if ( !xBindable.is() )
431             bAllow = false;
432 
433         // then, we must live in a spreadsheet document which can provide the special
434         // service needed for exchanging integer values
435         if ( bAllow )
436             bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_SHEET_CELL_INT_BINDING );
437 
438         // then, we only offer this for list boxes
439         if ( bAllow )
440         {
441             try
442             {
443                 sal_Int16 nClassId = FormComponentType::CONTROL;
444                 m_xControlModel->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
445                 if ( FormComponentType::LISTBOX != nClassId )
446                     bAllow = false;
447             }
448             catch( const Exception& )
449             {
450             	OSL_ENSURE( sal_False, "CellBindingHelper::isCellIntegerBindingAllowed: caught an exception!" );
451                     // are there really control models which survive isCellBindingAllowed, but don't have a ClassId
452                     // property?
453                 bAllow = false;
454             }
455         }
456 
457         return bAllow;
458     }
459 
460     //------------------------------------------------------------------------
isCellBindingAllowed() const461     bool CellBindingHelper::isCellBindingAllowed( ) const
462     {
463         bool bAllow( false );
464 
465         Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY );
466         if ( xBindable.is() )
467         {
468             // the control can potentially be bound to an external value
469             // Does it live within a Calc document, and is able to supply CellBindings?
470             bAllow = isSpreadsheetDocumentWhichSupplies( SERVICE_SHEET_CELL_BINDING );
471         }
472 
473         // disallow for some types
474         // TODO: shouldn't the XBindableValue supply a list of supported types, and we can distingusih
475         // using this list? The current behavior below is somewhat hackish ...
476         if ( bAllow )
477         {
478             try
479             {
480                 sal_Int16 nClassId = FormComponentType::CONTROL;
481                 m_xControlModel->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
482                 if ( ( FormComponentType::DATEFIELD == nClassId ) || ( FormComponentType::TIMEFIELD == nClassId ) )
483                     bAllow = false;
484             }
485             catch( const Exception& )
486             {
487             	OSL_ENSURE( sal_False, "CellBindingHelper::isCellBindingAllowed: caught an exception!" );
488                 bAllow = false;
489             }
490         }
491         return bAllow;
492     }
493 
494     //------------------------------------------------------------------------
isCellBinding(const Reference<XValueBinding> & _rxBinding) const495     bool CellBindingHelper::isCellBinding( const Reference< XValueBinding >& _rxBinding ) const
496     {
497         return doesComponentSupport( _rxBinding.get(), SERVICE_SHEET_CELL_BINDING );
498     }
499 
500     //------------------------------------------------------------------------
isCellIntegerBinding(const Reference<XValueBinding> & _rxBinding) const501     bool CellBindingHelper::isCellIntegerBinding( const Reference< XValueBinding >& _rxBinding ) const
502     {
503         return doesComponentSupport( _rxBinding.get(), SERVICE_SHEET_CELL_INT_BINDING );
504     }
505 
506     //------------------------------------------------------------------------
isCellRangeListSource(const Reference<XListEntrySource> & _rxSource) const507     bool CellBindingHelper::isCellRangeListSource( const Reference< XListEntrySource >& _rxSource ) const
508     {
509         return doesComponentSupport( _rxSource.get(), SERVICE_SHEET_CELLRANGE_LISTSOURCE );
510     }
511 
512     //------------------------------------------------------------------------
doesComponentSupport(const Reference<XInterface> & _rxComponent,const::rtl::OUString & _rService) const513     bool CellBindingHelper::doesComponentSupport( const Reference< XInterface >& _rxComponent, const ::rtl::OUString& _rService ) const
514     {
515         bool bDoes = false;
516         Reference< XServiceInfo > xSI( _rxComponent, UNO_QUERY );
517         bDoes = xSI.is() && xSI->supportsService( _rService );
518         return bDoes;
519     }
520 
521     //------------------------------------------------------------------------
getCurrentBinding() const522     Reference< XValueBinding > CellBindingHelper::getCurrentBinding( ) const
523     {
524         Reference< XValueBinding > xBinding;
525         Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY );
526         if ( xBindable.is() )
527             xBinding = xBindable->getValueBinding();
528         return xBinding;
529     }
530 
531     //------------------------------------------------------------------------
getCurrentListSource() const532     Reference< XListEntrySource > CellBindingHelper::getCurrentListSource( ) const
533     {
534         Reference< XListEntrySource > xSource;
535         Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY );
536         if ( xSink.is() )
537             xSource = xSink->getListEntrySource();
538         return xSource;
539     }
540 
541     //------------------------------------------------------------------------
setBinding(const Reference<XValueBinding> & _rxBinding)542     void CellBindingHelper::setBinding( const Reference< XValueBinding >& _rxBinding )
543     {
544         Reference< XBindableValue > xBindable( m_xControlModel, UNO_QUERY );
545         OSL_PRECOND( xBindable.is(), "CellBindingHelper::setBinding: the object is not bindable!" );
546         if ( xBindable.is() )
547             xBindable->setValueBinding( _rxBinding );
548     }
549 
550     //------------------------------------------------------------------------
setListSource(const Reference<XListEntrySource> & _rxSource)551     void CellBindingHelper::setListSource( const Reference< XListEntrySource >& _rxSource )
552     {
553         Reference< XListEntrySink > xSink( m_xControlModel, UNO_QUERY );
554         OSL_PRECOND( xSink.is(), "CellBindingHelper::setListSource: the object is no list entry sink!" );
555         if ( xSink.is() )
556             xSink->setListEntrySource( _rxSource );
557     }
558 
559 //............................................................................
560 }   // namespace pcr
561 //............................................................................
562