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