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