1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sc.hxx"
26*b1cdbd2cSJim Jagielski #include "cellvaluebinding.hxx"
27*b1cdbd2cSJim Jagielski #include <tools/debug.hxx>
28*b1cdbd2cSJim Jagielski #include <rtl/math.hxx>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/table/XCellRange.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/sheet/XCellAddressable.hpp>
31*b1cdbd2cSJim Jagielski #include <com/sun/star/sheet/XCellRangeData.hpp>
32*b1cdbd2cSJim Jagielski #include <com/sun/star/container/XIndexAccess.hpp>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/PropertyAttribute.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/NamedValue.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
36*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XNumberFormatTypes.hpp>
37*b1cdbd2cSJim Jagielski #include <com/sun/star/util/NumberFormat.hpp>
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski //.........................................................................
40*b1cdbd2cSJim Jagielski namespace calc
41*b1cdbd2cSJim Jagielski {
42*b1cdbd2cSJim Jagielski //.........................................................................
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski #define PROP_HANDLE_BOUND_CELL  1
45*b1cdbd2cSJim Jagielski 
46*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::uno;
47*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::lang;
48*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::table;
49*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::text;
50*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::sheet;
51*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::container;
52*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::beans;
53*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::util;
54*b1cdbd2cSJim Jagielski     using namespace ::com::sun::star::form::binding;
55*b1cdbd2cSJim Jagielski 
56*b1cdbd2cSJim Jagielski     //=====================================================================
57*b1cdbd2cSJim Jagielski     //= OCellValueBinding
58*b1cdbd2cSJim Jagielski     //=====================================================================
DBG_NAME(OCellValueBinding) const59*b1cdbd2cSJim Jagielski     DBG_NAME( OCellValueBinding )
60*b1cdbd2cSJim Jagielski     //---------------------------------------------------------------------
61*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL
62*b1cdbd2cSJim Jagielski     const char* OCellValueBinding::checkConsistency_static( const void* _pThis )
63*b1cdbd2cSJim Jagielski     {
64*b1cdbd2cSJim Jagielski         return static_cast< const OCellValueBinding* >( _pThis )->checkConsistency( );
65*b1cdbd2cSJim Jagielski     }
66*b1cdbd2cSJim Jagielski 
checkConsistency() const67*b1cdbd2cSJim Jagielski     const char* OCellValueBinding::checkConsistency( ) const
68*b1cdbd2cSJim Jagielski     {
69*b1cdbd2cSJim Jagielski         const char* pAssertion = NULL;
70*b1cdbd2cSJim Jagielski         if ( m_xCellText.is() && !m_xCell.is() )
71*b1cdbd2cSJim Jagielski             // there are places (e.g. getSupportedTypes) which rely on the fact
72*b1cdbd2cSJim Jagielski             // that m_xCellText.is() implies m_xCell.is()
73*b1cdbd2cSJim Jagielski             pAssertion = "cell references inconsistent!";
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski         // TODO: place any additional checks here to ensure consistency of this instance
76*b1cdbd2cSJim Jagielski         return pAssertion;
77*b1cdbd2cSJim Jagielski     }
78*b1cdbd2cSJim Jagielski #endif
79*b1cdbd2cSJim Jagielski 
80*b1cdbd2cSJim Jagielski     //---------------------------------------------------------------------
OCellValueBinding(const Reference<XSpreadsheetDocument> & _rxDocument,sal_Bool _bListPos)81*b1cdbd2cSJim Jagielski     OCellValueBinding::OCellValueBinding( const Reference< XSpreadsheetDocument >& _rxDocument, sal_Bool _bListPos )
82*b1cdbd2cSJim Jagielski         :OCellValueBinding_Base( m_aMutex )
83*b1cdbd2cSJim Jagielski         ,OCellValueBinding_PBase( OCellValueBinding_Base::rBHelper )
84*b1cdbd2cSJim Jagielski         ,m_xDocument( _rxDocument )
85*b1cdbd2cSJim Jagielski         ,m_aModifyListeners( m_aMutex )
86*b1cdbd2cSJim Jagielski         ,m_bInitialized( sal_False )
87*b1cdbd2cSJim Jagielski         ,m_bListPos( _bListPos )
88*b1cdbd2cSJim Jagielski     {
89*b1cdbd2cSJim Jagielski         DBG_CTOR( OCellValueBinding, checkConsistency_static );
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski         // register our property at the base class
92*b1cdbd2cSJim Jagielski         CellAddress aInitialPropValue;
93*b1cdbd2cSJim Jagielski         registerPropertyNoMember(
94*b1cdbd2cSJim Jagielski             ::rtl::OUString::createFromAscii( "BoundCell" ),
95*b1cdbd2cSJim Jagielski             PROP_HANDLE_BOUND_CELL,
96*b1cdbd2cSJim Jagielski             PropertyAttribute::BOUND | PropertyAttribute::READONLY,
97*b1cdbd2cSJim Jagielski             ::getCppuType( &aInitialPropValue ),
98*b1cdbd2cSJim Jagielski             &aInitialPropValue
99*b1cdbd2cSJim Jagielski         );
100*b1cdbd2cSJim Jagielski 
101*b1cdbd2cSJim Jagielski         // TODO: implement a ReadOnly property as required by the service,
102*b1cdbd2cSJim Jagielski         // which probably maps to the cell being locked
103*b1cdbd2cSJim Jagielski     }
104*b1cdbd2cSJim Jagielski 
105*b1cdbd2cSJim Jagielski     //---------------------------------------------------------------------
~OCellValueBinding()106*b1cdbd2cSJim Jagielski     OCellValueBinding::~OCellValueBinding( )
107*b1cdbd2cSJim Jagielski     {
108*b1cdbd2cSJim Jagielski         if ( !OCellValueBinding_Base::rBHelper.bDisposed )
109*b1cdbd2cSJim Jagielski         {
110*b1cdbd2cSJim Jagielski             acquire();  // prevent duplicate dtor
111*b1cdbd2cSJim Jagielski             dispose();
112*b1cdbd2cSJim Jagielski         }
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski         DBG_DTOR( OCellValueBinding, checkConsistency_static );
115*b1cdbd2cSJim Jagielski     }
116*b1cdbd2cSJim Jagielski 
117*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(OCellValueBinding,OCellValueBinding_Base,OCellValueBinding_PBase)118*b1cdbd2cSJim Jagielski     IMPLEMENT_FORWARD_XINTERFACE2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase )
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
121*b1cdbd2cSJim Jagielski     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase )
122*b1cdbd2cSJim Jagielski 
123*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
124*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::disposing()
125*b1cdbd2cSJim Jagielski     {
126*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
127*b1cdbd2cSJim Jagielski 
128*b1cdbd2cSJim Jagielski         Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY );
129*b1cdbd2cSJim Jagielski         if ( xBroadcaster.is() )
130*b1cdbd2cSJim Jagielski         {
131*b1cdbd2cSJim Jagielski             xBroadcaster->removeModifyListener( this );
132*b1cdbd2cSJim Jagielski         }
133*b1cdbd2cSJim Jagielski 
134*b1cdbd2cSJim Jagielski //        OCellValueBinding_Base::disposing();
135*b1cdbd2cSJim Jagielski         WeakAggComponentImplHelperBase::disposing();
136*b1cdbd2cSJim Jagielski 
137*b1cdbd2cSJim Jagielski         // TODO: clean up here whatever you need to clean up (e.g. deregister as XEventListener
138*b1cdbd2cSJim Jagielski         // for the cell)
139*b1cdbd2cSJim Jagielski     }
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getPropertySetInfo()142*b1cdbd2cSJim Jagielski     Reference< XPropertySetInfo > SAL_CALL OCellValueBinding::getPropertySetInfo(  ) throw(RuntimeException)
143*b1cdbd2cSJim Jagielski     {
144*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
145*b1cdbd2cSJim Jagielski         return createPropertySetInfo( getInfoHelper() ) ;
146*b1cdbd2cSJim Jagielski     }
147*b1cdbd2cSJim Jagielski 
148*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getInfoHelper()149*b1cdbd2cSJim Jagielski     ::cppu::IPropertyArrayHelper& SAL_CALL OCellValueBinding::getInfoHelper()
150*b1cdbd2cSJim Jagielski     {
151*b1cdbd2cSJim Jagielski         return *OCellValueBinding_PABase::getArrayHelper();
152*b1cdbd2cSJim Jagielski     }
153*b1cdbd2cSJim Jagielski 
154*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
createArrayHelper() const155*b1cdbd2cSJim Jagielski     ::cppu::IPropertyArrayHelper* OCellValueBinding::createArrayHelper( ) const
156*b1cdbd2cSJim Jagielski     {
157*b1cdbd2cSJim Jagielski         Sequence< Property > aProps;
158*b1cdbd2cSJim Jagielski         describeProperties( aProps );
159*b1cdbd2cSJim Jagielski         return new ::cppu::OPropertyArrayHelper(aProps);
160*b1cdbd2cSJim Jagielski     }
161*b1cdbd2cSJim Jagielski 
162*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const163*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
164*b1cdbd2cSJim Jagielski     {
165*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
166*b1cdbd2cSJim Jagielski         DBG_ASSERT( _nHandle == PROP_HANDLE_BOUND_CELL, "OCellValueBinding::getFastPropertyValue: invalid handle!" );
167*b1cdbd2cSJim Jagielski             // we only have this one property ....
168*b1cdbd2cSJim Jagielski         (void)_nHandle;     // avoid warning in product version
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski         _rValue.clear();
171*b1cdbd2cSJim Jagielski         Reference< XCellAddressable > xCellAddress( m_xCell, UNO_QUERY );
172*b1cdbd2cSJim Jagielski         if ( xCellAddress.is() )
173*b1cdbd2cSJim Jagielski             _rValue <<= xCellAddress->getCellAddress( );
174*b1cdbd2cSJim Jagielski     }
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getSupportedValueTypes()177*b1cdbd2cSJim Jagielski     Sequence< Type > SAL_CALL OCellValueBinding::getSupportedValueTypes(  ) throw (RuntimeException)
178*b1cdbd2cSJim Jagielski     {
179*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
180*b1cdbd2cSJim Jagielski         checkDisposed( );
181*b1cdbd2cSJim Jagielski         checkInitialized( );
182*b1cdbd2cSJim Jagielski 
183*b1cdbd2cSJim Jagielski         sal_Int32 nCount = m_xCellText.is() ? 3 : m_xCell.is() ? 1 : 0;
184*b1cdbd2cSJim Jagielski         if ( m_bListPos )
185*b1cdbd2cSJim Jagielski             ++nCount;
186*b1cdbd2cSJim Jagielski 
187*b1cdbd2cSJim Jagielski         Sequence< Type > aTypes( nCount );
188*b1cdbd2cSJim Jagielski         if ( m_xCell.is() )
189*b1cdbd2cSJim Jagielski         {
190*b1cdbd2cSJim Jagielski             // an XCell can be used to set/get "double" values
191*b1cdbd2cSJim Jagielski             aTypes[0] = ::getCppuType( static_cast< double* >( NULL ) );
192*b1cdbd2cSJim Jagielski             if ( m_xCellText.is() )
193*b1cdbd2cSJim Jagielski             {
194*b1cdbd2cSJim Jagielski                 // an XTextRange can be used to set/get "string" values
195*b1cdbd2cSJim Jagielski                 aTypes[1] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
196*b1cdbd2cSJim Jagielski                 // and additionally, we use it to handle booleans
197*b1cdbd2cSJim Jagielski                 aTypes[2] = ::getCppuType( static_cast< sal_Bool* >( NULL ) );
198*b1cdbd2cSJim Jagielski             }
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski             // add sal_Int32 only if constructed as ListPositionCellBinding
201*b1cdbd2cSJim Jagielski             if ( m_bListPos )
202*b1cdbd2cSJim Jagielski                 aTypes[nCount-1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) );
203*b1cdbd2cSJim Jagielski         }
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski         return aTypes;
206*b1cdbd2cSJim Jagielski     }
207*b1cdbd2cSJim Jagielski 
208*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
supportsType(const Type & aType)209*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL OCellValueBinding::supportsType( const Type& aType ) throw (RuntimeException)
210*b1cdbd2cSJim Jagielski     {
211*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
212*b1cdbd2cSJim Jagielski         checkDisposed( );
213*b1cdbd2cSJim Jagielski         checkInitialized( );
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski         // look up in our sequence
216*b1cdbd2cSJim Jagielski         Sequence< Type > aSupportedTypes( getSupportedValueTypes() );
217*b1cdbd2cSJim Jagielski         const Type* pTypes = aSupportedTypes.getConstArray();
218*b1cdbd2cSJim Jagielski         const Type* pTypesEnd = aSupportedTypes.getConstArray() + aSupportedTypes.getLength();
219*b1cdbd2cSJim Jagielski         while ( pTypes != pTypesEnd )
220*b1cdbd2cSJim Jagielski             if ( aType.equals( *pTypes++ ) )
221*b1cdbd2cSJim Jagielski                 return sal_True;
222*b1cdbd2cSJim Jagielski 
223*b1cdbd2cSJim Jagielski         return sal_False;
224*b1cdbd2cSJim Jagielski     }
225*b1cdbd2cSJim Jagielski 
226*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getValue(const Type & aType)227*b1cdbd2cSJim Jagielski     Any SAL_CALL OCellValueBinding::getValue( const Type& aType ) throw (IncompatibleTypesException, RuntimeException)
228*b1cdbd2cSJim Jagielski     {
229*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
230*b1cdbd2cSJim Jagielski         checkDisposed( );
231*b1cdbd2cSJim Jagielski         checkInitialized( );
232*b1cdbd2cSJim Jagielski         checkValueType( aType );
233*b1cdbd2cSJim Jagielski 
234*b1cdbd2cSJim Jagielski         Any aReturn;
235*b1cdbd2cSJim Jagielski         switch ( aType.getTypeClass() )
236*b1cdbd2cSJim Jagielski         {
237*b1cdbd2cSJim Jagielski         case TypeClass_STRING:
238*b1cdbd2cSJim Jagielski             DBG_ASSERT( m_xCellText.is(), "OCellValueBinding::getValue: don't have a text!" );
239*b1cdbd2cSJim Jagielski             if ( m_xCellText.is() )
240*b1cdbd2cSJim Jagielski                 aReturn <<= m_xCellText->getString();
241*b1cdbd2cSJim Jagielski             else
242*b1cdbd2cSJim Jagielski                 aReturn <<= ::rtl::OUString();
243*b1cdbd2cSJim Jagielski             break;
244*b1cdbd2cSJim Jagielski 
245*b1cdbd2cSJim Jagielski         case TypeClass_BOOLEAN:
246*b1cdbd2cSJim Jagielski             DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
247*b1cdbd2cSJim Jagielski             if ( m_xCell.is() )
248*b1cdbd2cSJim Jagielski             {
249*b1cdbd2cSJim Jagielski                 // check if the cell has a numeric value (this might go into a helper function):
250*b1cdbd2cSJim Jagielski 
251*b1cdbd2cSJim Jagielski                 sal_Bool bHasValue = sal_False;
252*b1cdbd2cSJim Jagielski                 CellContentType eCellType = m_xCell->getType();
253*b1cdbd2cSJim Jagielski                 if ( eCellType == CellContentType_VALUE )
254*b1cdbd2cSJim Jagielski                     bHasValue = sal_True;
255*b1cdbd2cSJim Jagielski                 else if ( eCellType == CellContentType_FORMULA )
256*b1cdbd2cSJim Jagielski                 {
257*b1cdbd2cSJim Jagielski                     // check if the formula result is a value
258*b1cdbd2cSJim Jagielski                     if ( m_xCell->getError() == 0 )
259*b1cdbd2cSJim Jagielski                     {
260*b1cdbd2cSJim Jagielski                         Reference<XPropertySet> xProp( m_xCell, UNO_QUERY );
261*b1cdbd2cSJim Jagielski                         if ( xProp.is() )
262*b1cdbd2cSJim Jagielski                         {
263*b1cdbd2cSJim Jagielski                             CellContentType eResultType;
264*b1cdbd2cSJim Jagielski                             if ( (xProp->getPropertyValue(::rtl::OUString::createFromAscii( "FormulaResultType" ) ) >>= eResultType) && eResultType == CellContentType_VALUE )
265*b1cdbd2cSJim Jagielski                                 bHasValue = sal_True;
266*b1cdbd2cSJim Jagielski                         }
267*b1cdbd2cSJim Jagielski                     }
268*b1cdbd2cSJim Jagielski                 }
269*b1cdbd2cSJim Jagielski 
270*b1cdbd2cSJim Jagielski                 if ( bHasValue )
271*b1cdbd2cSJim Jagielski                 {
272*b1cdbd2cSJim Jagielski                     // 0 is "unchecked", any other value is "checked", regardless of number format
273*b1cdbd2cSJim Jagielski                     double nCellValue = m_xCell->getValue();
274*b1cdbd2cSJim Jagielski                     sal_Bool bBoolValue = ( nCellValue != 0.0 );
275*b1cdbd2cSJim Jagielski                     aReturn <<= bBoolValue;
276*b1cdbd2cSJim Jagielski                 }
277*b1cdbd2cSJim Jagielski                 // empty cells, text cells and text or error formula results: leave return value empty
278*b1cdbd2cSJim Jagielski             }
279*b1cdbd2cSJim Jagielski             break;
280*b1cdbd2cSJim Jagielski 
281*b1cdbd2cSJim Jagielski         case TypeClass_DOUBLE:
282*b1cdbd2cSJim Jagielski             DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
283*b1cdbd2cSJim Jagielski             if ( m_xCell.is() )
284*b1cdbd2cSJim Jagielski                 aReturn <<= m_xCell->getValue();
285*b1cdbd2cSJim Jagielski             else
286*b1cdbd2cSJim Jagielski                 aReturn <<= (double)0;
287*b1cdbd2cSJim Jagielski             break;
288*b1cdbd2cSJim Jagielski 
289*b1cdbd2cSJim Jagielski         case TypeClass_LONG:
290*b1cdbd2cSJim Jagielski             DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
291*b1cdbd2cSJim Jagielski             if ( m_xCell.is() )
292*b1cdbd2cSJim Jagielski             {
293*b1cdbd2cSJim Jagielski                 // The list position value in the cell is 1-based.
294*b1cdbd2cSJim Jagielski                 // We subtract 1 from any cell value (no special handling for 0 or negative values).
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski                 sal_Int32 nValue = (sal_Int32) rtl::math::approxFloor( m_xCell->getValue() );
297*b1cdbd2cSJim Jagielski                 --nValue;
298*b1cdbd2cSJim Jagielski 
299*b1cdbd2cSJim Jagielski                 aReturn <<= nValue;
300*b1cdbd2cSJim Jagielski             }
301*b1cdbd2cSJim Jagielski             else
302*b1cdbd2cSJim Jagielski                 aReturn <<= (sal_Int32)0;
303*b1cdbd2cSJim Jagielski             break;
304*b1cdbd2cSJim Jagielski 
305*b1cdbd2cSJim Jagielski         default:
306*b1cdbd2cSJim Jagielski             DBG_ERROR( "OCellValueBinding::getValue: unreachable code!" );
307*b1cdbd2cSJim Jagielski                 // a type other than double and string should never have survived the checkValueType
308*b1cdbd2cSJim Jagielski                 // above
309*b1cdbd2cSJim Jagielski         }
310*b1cdbd2cSJim Jagielski         return aReturn;
311*b1cdbd2cSJim Jagielski     }
312*b1cdbd2cSJim Jagielski 
313*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
setValue(const Any & aValue)314*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::setValue( const Any& aValue ) throw (IncompatibleTypesException, NoSupportException, RuntimeException)
315*b1cdbd2cSJim Jagielski     {
316*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
317*b1cdbd2cSJim Jagielski         checkDisposed( );
318*b1cdbd2cSJim Jagielski         checkInitialized( );
319*b1cdbd2cSJim Jagielski         if ( aValue.hasValue() )
320*b1cdbd2cSJim Jagielski             checkValueType( aValue.getValueType() );
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski         switch ( aValue.getValueType().getTypeClass() )
323*b1cdbd2cSJim Jagielski         {
324*b1cdbd2cSJim Jagielski         case TypeClass_STRING:
325*b1cdbd2cSJim Jagielski             {
326*b1cdbd2cSJim Jagielski                 DBG_ASSERT( m_xCellText.is(), "OCellValueBinding::setValue: don't have a text!" );
327*b1cdbd2cSJim Jagielski 
328*b1cdbd2cSJim Jagielski                 ::rtl::OUString sText;
329*b1cdbd2cSJim Jagielski                 aValue >>= sText;
330*b1cdbd2cSJim Jagielski                 if ( m_xCellText.is() )
331*b1cdbd2cSJim Jagielski                     m_xCellText->setString( sText );
332*b1cdbd2cSJim Jagielski             }
333*b1cdbd2cSJim Jagielski             break;
334*b1cdbd2cSJim Jagielski 
335*b1cdbd2cSJim Jagielski         case TypeClass_BOOLEAN:
336*b1cdbd2cSJim Jagielski             {
337*b1cdbd2cSJim Jagielski                 DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
338*b1cdbd2cSJim Jagielski 
339*b1cdbd2cSJim Jagielski                 // boolean is stored as values 0 or 1
340*b1cdbd2cSJim Jagielski                 // TODO: set the number format to boolean if no format is set?
341*b1cdbd2cSJim Jagielski 
342*b1cdbd2cSJim Jagielski                 sal_Bool bValue( sal_False );
343*b1cdbd2cSJim Jagielski                 aValue >>= bValue;
344*b1cdbd2cSJim Jagielski                 double nCellValue = bValue ? 1.0 : 0.0;
345*b1cdbd2cSJim Jagielski 
346*b1cdbd2cSJim Jagielski                 if ( m_xCell.is() )
347*b1cdbd2cSJim Jagielski                     m_xCell->setValue( nCellValue );
348*b1cdbd2cSJim Jagielski 
349*b1cdbd2cSJim Jagielski                 setBooleanFormat();
350*b1cdbd2cSJim Jagielski             }
351*b1cdbd2cSJim Jagielski             break;
352*b1cdbd2cSJim Jagielski 
353*b1cdbd2cSJim Jagielski         case TypeClass_DOUBLE:
354*b1cdbd2cSJim Jagielski             {
355*b1cdbd2cSJim Jagielski                 DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
356*b1cdbd2cSJim Jagielski 
357*b1cdbd2cSJim Jagielski                 double nValue = 0;
358*b1cdbd2cSJim Jagielski                 aValue >>= nValue;
359*b1cdbd2cSJim Jagielski                 if ( m_xCell.is() )
360*b1cdbd2cSJim Jagielski                     m_xCell->setValue( nValue );
361*b1cdbd2cSJim Jagielski             }
362*b1cdbd2cSJim Jagielski             break;
363*b1cdbd2cSJim Jagielski 
364*b1cdbd2cSJim Jagielski         case TypeClass_LONG:
365*b1cdbd2cSJim Jagielski             {
366*b1cdbd2cSJim Jagielski                 DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
367*b1cdbd2cSJim Jagielski 
368*b1cdbd2cSJim Jagielski                 sal_Int32 nValue = 0;
369*b1cdbd2cSJim Jagielski                 aValue >>= nValue;      // list index from control layer (0-based)
370*b1cdbd2cSJim Jagielski                 ++nValue;               // the list position value in the cell is 1-based
371*b1cdbd2cSJim Jagielski                 if ( m_xCell.is() )
372*b1cdbd2cSJim Jagielski                     m_xCell->setValue( nValue );
373*b1cdbd2cSJim Jagielski             }
374*b1cdbd2cSJim Jagielski             break;
375*b1cdbd2cSJim Jagielski 
376*b1cdbd2cSJim Jagielski         case TypeClass_VOID:
377*b1cdbd2cSJim Jagielski             {
378*b1cdbd2cSJim Jagielski                 // #N/A error value can only be set using XCellRangeData
379*b1cdbd2cSJim Jagielski 
380*b1cdbd2cSJim Jagielski             	Reference<XCellRangeData> xData( m_xCell, UNO_QUERY );
381*b1cdbd2cSJim Jagielski                 DBG_ASSERT( xData.is(), "OCellValueBinding::setValue: don't have XCellRangeData!" );
382*b1cdbd2cSJim Jagielski                 if ( xData.is() )
383*b1cdbd2cSJim Jagielski                 {
384*b1cdbd2cSJim Jagielski                     Sequence<Any> aInner(1);                            // one empty element
385*b1cdbd2cSJim Jagielski                     Sequence< Sequence<Any> > aOuter( &aInner, 1 );     // one row
386*b1cdbd2cSJim Jagielski                     xData->setDataArray( aOuter );
387*b1cdbd2cSJim Jagielski                 }
388*b1cdbd2cSJim Jagielski             }
389*b1cdbd2cSJim Jagielski             break;
390*b1cdbd2cSJim Jagielski 
391*b1cdbd2cSJim Jagielski         default:
392*b1cdbd2cSJim Jagielski             DBG_ERROR( "OCellValueBinding::setValue: unreachable code!" );
393*b1cdbd2cSJim Jagielski                 // a type other than double and string should never have survived the checkValueType
394*b1cdbd2cSJim Jagielski                 // above
395*b1cdbd2cSJim Jagielski         }
396*b1cdbd2cSJim Jagielski     }
397*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
setBooleanFormat()398*b1cdbd2cSJim Jagielski     void OCellValueBinding::setBooleanFormat()
399*b1cdbd2cSJim Jagielski     {
400*b1cdbd2cSJim Jagielski         // set boolean number format if not already set
401*b1cdbd2cSJim Jagielski 
402*b1cdbd2cSJim Jagielski         ::rtl::OUString sPropName( ::rtl::OUString::createFromAscii( "NumberFormat" ) );
403*b1cdbd2cSJim Jagielski         Reference<XPropertySet> xCellProp( m_xCell, UNO_QUERY );
404*b1cdbd2cSJim Jagielski         Reference<XNumberFormatsSupplier> xSupplier( m_xDocument, UNO_QUERY );
405*b1cdbd2cSJim Jagielski         if ( xSupplier.is() && xCellProp.is() )
406*b1cdbd2cSJim Jagielski         {
407*b1cdbd2cSJim Jagielski             Reference<XNumberFormats> xFormats(xSupplier->getNumberFormats());
408*b1cdbd2cSJim Jagielski         	Reference<XNumberFormatTypes> xTypes( xFormats, UNO_QUERY );
409*b1cdbd2cSJim Jagielski         	if ( xTypes.is() )
410*b1cdbd2cSJim Jagielski         	{
411*b1cdbd2cSJim Jagielski         		Locale aLocale;
412*b1cdbd2cSJim Jagielski         		sal_Bool bWasBoolean = sal_False;
413*b1cdbd2cSJim Jagielski 
414*b1cdbd2cSJim Jagielski         		sal_Int32 nOldIndex = ::comphelper::getINT32( xCellProp->getPropertyValue( sPropName ) );
415*b1cdbd2cSJim Jagielski 				Reference<XPropertySet> xOldFormat;
416*b1cdbd2cSJim Jagielski                 try
417*b1cdbd2cSJim Jagielski                 {
418*b1cdbd2cSJim Jagielski         		    xOldFormat.set(xFormats->getByKey( nOldIndex ));
419*b1cdbd2cSJim Jagielski                 }
420*b1cdbd2cSJim Jagielski                 catch ( Exception& )
421*b1cdbd2cSJim Jagielski                 {
422*b1cdbd2cSJim Jagielski                     // non-existing format - can happen, use defaults
423*b1cdbd2cSJim Jagielski                 }
424*b1cdbd2cSJim Jagielski                 if ( xOldFormat.is() )
425*b1cdbd2cSJim Jagielski                 {
426*b1cdbd2cSJim Jagielski                     // use the locale of the existing format
427*b1cdbd2cSJim Jagielski                     xOldFormat->getPropertyValue( ::rtl::OUString::createFromAscii( "Locale" ) ) >>= aLocale;
428*b1cdbd2cSJim Jagielski 
429*b1cdbd2cSJim Jagielski                     sal_Int16 nOldType = ::comphelper::getINT16(
430*b1cdbd2cSJim Jagielski                     	xOldFormat->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) );
431*b1cdbd2cSJim Jagielski                     if ( nOldType & NumberFormat::LOGICAL )
432*b1cdbd2cSJim Jagielski                     	bWasBoolean = sal_True;
433*b1cdbd2cSJim Jagielski                 }
434*b1cdbd2cSJim Jagielski 
435*b1cdbd2cSJim Jagielski         		if ( !bWasBoolean )
436*b1cdbd2cSJim Jagielski         		{
437*b1cdbd2cSJim Jagielski         		    sal_Int32 nNewIndex = xTypes->getStandardFormat( NumberFormat::LOGICAL, aLocale );
438*b1cdbd2cSJim Jagielski         		    xCellProp->setPropertyValue( sPropName, makeAny( nNewIndex ) );
439*b1cdbd2cSJim Jagielski         		}
440*b1cdbd2cSJim Jagielski         	}
441*b1cdbd2cSJim Jagielski         }
442*b1cdbd2cSJim Jagielski     }
443*b1cdbd2cSJim Jagielski 
444*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
checkDisposed() const445*b1cdbd2cSJim Jagielski     void OCellValueBinding::checkDisposed( ) const SAL_THROW( ( DisposedException ) )
446*b1cdbd2cSJim Jagielski     {
447*b1cdbd2cSJim Jagielski         if ( OCellValueBinding_Base::rBHelper.bInDispose || OCellValueBinding_Base::rBHelper.bDisposed )
448*b1cdbd2cSJim Jagielski             throw DisposedException();
449*b1cdbd2cSJim Jagielski             // TODO: is it worth having an error message here?
450*b1cdbd2cSJim Jagielski     }
451*b1cdbd2cSJim Jagielski 
452*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
checkInitialized()453*b1cdbd2cSJim Jagielski     void OCellValueBinding::checkInitialized() SAL_THROW( ( RuntimeException ) )
454*b1cdbd2cSJim Jagielski     {
455*b1cdbd2cSJim Jagielski         if ( !m_bInitialized )
456*b1cdbd2cSJim Jagielski             throw RuntimeException();
457*b1cdbd2cSJim Jagielski             // TODO: error message
458*b1cdbd2cSJim Jagielski     }
459*b1cdbd2cSJim Jagielski 
460*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
checkValueType(const Type & _rType) const461*b1cdbd2cSJim Jagielski     void OCellValueBinding::checkValueType( const Type& _rType ) const SAL_THROW( ( IncompatibleTypesException ) )
462*b1cdbd2cSJim Jagielski     {
463*b1cdbd2cSJim Jagielski         OCellValueBinding* pNonConstThis = const_cast< OCellValueBinding* >( this );
464*b1cdbd2cSJim Jagielski         if ( !pNonConstThis->supportsType( _rType ) )
465*b1cdbd2cSJim Jagielski         {
466*b1cdbd2cSJim Jagielski             ::rtl::OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "The given type (" ) );
467*b1cdbd2cSJim Jagielski             sMessage += _rType.getTypeName();
468*b1cdbd2cSJim Jagielski             sMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ") is not supported by this binding." ) );
469*b1cdbd2cSJim Jagielski                 // TODO: localize this error message
470*b1cdbd2cSJim Jagielski 
471*b1cdbd2cSJim Jagielski             throw IncompatibleTypesException( sMessage, *pNonConstThis );
472*b1cdbd2cSJim Jagielski                 // TODO: alternatively use a type converter service for this?
473*b1cdbd2cSJim Jagielski         }
474*b1cdbd2cSJim Jagielski     }
475*b1cdbd2cSJim Jagielski 
476*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getImplementationName()477*b1cdbd2cSJim Jagielski     ::rtl::OUString SAL_CALL OCellValueBinding::getImplementationName(  ) throw (RuntimeException)
478*b1cdbd2cSJim Jagielski     {
479*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
480*b1cdbd2cSJim Jagielski 
481*b1cdbd2cSJim Jagielski         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sheet.OCellValueBinding" ) );
482*b1cdbd2cSJim Jagielski     }
483*b1cdbd2cSJim Jagielski 
484*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)485*b1cdbd2cSJim Jagielski     sal_Bool SAL_CALL OCellValueBinding::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
486*b1cdbd2cSJim Jagielski     {
487*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
488*b1cdbd2cSJim Jagielski 
489*b1cdbd2cSJim Jagielski         Sequence< ::rtl::OUString > aSupportedServices( getSupportedServiceNames() );
490*b1cdbd2cSJim Jagielski         const ::rtl::OUString* pLookup = aSupportedServices.getConstArray();
491*b1cdbd2cSJim Jagielski         const ::rtl::OUString* pLookupEnd = aSupportedServices.getConstArray() + aSupportedServices.getLength();
492*b1cdbd2cSJim Jagielski         while ( pLookup != pLookupEnd )
493*b1cdbd2cSJim Jagielski             if ( *pLookup++ == _rServiceName )
494*b1cdbd2cSJim Jagielski                 return sal_True;
495*b1cdbd2cSJim Jagielski 
496*b1cdbd2cSJim Jagielski         return sal_False;
497*b1cdbd2cSJim Jagielski     }
498*b1cdbd2cSJim Jagielski 
499*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
getSupportedServiceNames()500*b1cdbd2cSJim Jagielski     Sequence< ::rtl::OUString > SAL_CALL OCellValueBinding::getSupportedServiceNames(  ) throw (RuntimeException)
501*b1cdbd2cSJim Jagielski     {
502*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
503*b1cdbd2cSJim Jagielski 
504*b1cdbd2cSJim Jagielski         Sequence< ::rtl::OUString > aServices( m_bListPos ? 3 : 2 );
505*b1cdbd2cSJim Jagielski         aServices[ 0 ] =  ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.CellValueBinding" ) );
506*b1cdbd2cSJim Jagielski         aServices[ 1 ] =  ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.binding.ValueBinding" ) );
507*b1cdbd2cSJim Jagielski         if ( m_bListPos )
508*b1cdbd2cSJim Jagielski             aServices[ 2 ] =  ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.ListPositionCellBinding" ) );
509*b1cdbd2cSJim Jagielski         return aServices;
510*b1cdbd2cSJim Jagielski     }
511*b1cdbd2cSJim Jagielski 
512*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
addModifyListener(const Reference<XModifyListener> & _rxListener)513*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::addModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException)
514*b1cdbd2cSJim Jagielski     {
515*b1cdbd2cSJim Jagielski        if ( _rxListener.is() )
516*b1cdbd2cSJim Jagielski            m_aModifyListeners.addInterface( _rxListener );
517*b1cdbd2cSJim Jagielski     }
518*b1cdbd2cSJim Jagielski 
519*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
removeModifyListener(const Reference<XModifyListener> & _rxListener)520*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::removeModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException)
521*b1cdbd2cSJim Jagielski     {
522*b1cdbd2cSJim Jagielski        if ( _rxListener.is() )
523*b1cdbd2cSJim Jagielski            m_aModifyListeners.removeInterface( _rxListener );
524*b1cdbd2cSJim Jagielski     }
525*b1cdbd2cSJim Jagielski 
526*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
notifyModified()527*b1cdbd2cSJim Jagielski     void OCellValueBinding::notifyModified()
528*b1cdbd2cSJim Jagielski     {
529*b1cdbd2cSJim Jagielski         EventObject aEvent;
530*b1cdbd2cSJim Jagielski         aEvent.Source.set(*this);
531*b1cdbd2cSJim Jagielski 
532*b1cdbd2cSJim Jagielski         ::cppu::OInterfaceIteratorHelper aIter( m_aModifyListeners );
533*b1cdbd2cSJim Jagielski         while ( aIter.hasMoreElements() )
534*b1cdbd2cSJim Jagielski         {
535*b1cdbd2cSJim Jagielski             try
536*b1cdbd2cSJim Jagielski             {
537*b1cdbd2cSJim Jagielski                 static_cast< XModifyListener* >( aIter.next() )->modified( aEvent );
538*b1cdbd2cSJim Jagielski             }
539*b1cdbd2cSJim Jagielski             catch( const RuntimeException& )
540*b1cdbd2cSJim Jagielski             {
541*b1cdbd2cSJim Jagielski                 // silent this
542*b1cdbd2cSJim Jagielski             }
543*b1cdbd2cSJim Jagielski             catch( const Exception& )
544*b1cdbd2cSJim Jagielski             {
545*b1cdbd2cSJim Jagielski                 DBG_ERROR( "OCellValueBinding::notifyModified: caught a (non-runtime) exception!" );
546*b1cdbd2cSJim Jagielski             }
547*b1cdbd2cSJim Jagielski         }
548*b1cdbd2cSJim Jagielski     }
549*b1cdbd2cSJim Jagielski 
550*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
modified(const EventObject &)551*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::modified( const EventObject& /* aEvent */ ) throw (RuntimeException)
552*b1cdbd2cSJim Jagielski     {
553*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
554*b1cdbd2cSJim Jagielski 
555*b1cdbd2cSJim Jagielski         notifyModified();
556*b1cdbd2cSJim Jagielski     }
557*b1cdbd2cSJim Jagielski 
558*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
disposing(const EventObject & aEvent)559*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::disposing( const EventObject& aEvent ) throw (RuntimeException)
560*b1cdbd2cSJim Jagielski     {
561*b1cdbd2cSJim Jagielski         DBG_CHKTHIS( OCellValueBinding, checkConsistency_static );
562*b1cdbd2cSJim Jagielski 
563*b1cdbd2cSJim Jagielski         Reference<XInterface> xCellInt( m_xCell, UNO_QUERY );
564*b1cdbd2cSJim Jagielski         if ( xCellInt == aEvent.Source )
565*b1cdbd2cSJim Jagielski         {
566*b1cdbd2cSJim Jagielski             // release references to cell object
567*b1cdbd2cSJim Jagielski             m_xCell.clear();
568*b1cdbd2cSJim Jagielski             m_xCellText.clear();
569*b1cdbd2cSJim Jagielski         }
570*b1cdbd2cSJim Jagielski     }
571*b1cdbd2cSJim Jagielski 
572*b1cdbd2cSJim Jagielski     //--------------------------------------------------------------------
initialize(const Sequence<Any> & _rArguments)573*b1cdbd2cSJim Jagielski     void SAL_CALL OCellValueBinding::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
574*b1cdbd2cSJim Jagielski     {
575*b1cdbd2cSJim Jagielski         if ( m_bInitialized )
576*b1cdbd2cSJim Jagielski             throw Exception();
577*b1cdbd2cSJim Jagielski             // TODO: error message
578*b1cdbd2cSJim Jagielski 
579*b1cdbd2cSJim Jagielski         // get the cell address
580*b1cdbd2cSJim Jagielski         CellAddress aAddress;
581*b1cdbd2cSJim Jagielski         sal_Bool bFoundAddress = sal_False;
582*b1cdbd2cSJim Jagielski 
583*b1cdbd2cSJim Jagielski         const Any* pLoop = _rArguments.getConstArray();
584*b1cdbd2cSJim Jagielski         const Any* pLoopEnd = _rArguments.getConstArray() + _rArguments.getLength();
585*b1cdbd2cSJim Jagielski         for ( ; ( pLoop != pLoopEnd ) && !bFoundAddress; ++pLoop )
586*b1cdbd2cSJim Jagielski         {
587*b1cdbd2cSJim Jagielski             NamedValue aValue;
588*b1cdbd2cSJim Jagielski             if ( *pLoop >>= aValue )
589*b1cdbd2cSJim Jagielski             {
590*b1cdbd2cSJim Jagielski                 if ( aValue.Name.equalsAscii( "BoundCell" ) )
591*b1cdbd2cSJim Jagielski                 {
592*b1cdbd2cSJim Jagielski                     if ( aValue.Value >>= aAddress )
593*b1cdbd2cSJim Jagielski                         bFoundAddress = sal_True;
594*b1cdbd2cSJim Jagielski                 }
595*b1cdbd2cSJim Jagielski             }
596*b1cdbd2cSJim Jagielski         }
597*b1cdbd2cSJim Jagielski 
598*b1cdbd2cSJim Jagielski         if ( !bFoundAddress )
599*b1cdbd2cSJim Jagielski             // TODO: error message
600*b1cdbd2cSJim Jagielski             throw Exception();
601*b1cdbd2cSJim Jagielski 
602*b1cdbd2cSJim Jagielski         // get the cell object
603*b1cdbd2cSJim Jagielski         try
604*b1cdbd2cSJim Jagielski         {
605*b1cdbd2cSJim Jagielski             // first the sheets collection
606*b1cdbd2cSJim Jagielski             Reference< XIndexAccess > xSheets;
607*b1cdbd2cSJim Jagielski             if ( m_xDocument.is() )
608*b1cdbd2cSJim Jagielski                 xSheets.set(xSheets.query( m_xDocument->getSheets( ) ));
609*b1cdbd2cSJim Jagielski             DBG_ASSERT( xSheets.is(), "OCellValueBinding::initialize: could not retrieve the sheets!" );
610*b1cdbd2cSJim Jagielski 
611*b1cdbd2cSJim Jagielski             if ( xSheets.is() )
612*b1cdbd2cSJim Jagielski             {
613*b1cdbd2cSJim Jagielski                 // the concrete sheet
614*b1cdbd2cSJim Jagielski                 Reference< XCellRange > xSheet(xSheets->getByIndex( aAddress.Sheet ), UNO_QUERY);
615*b1cdbd2cSJim Jagielski                 DBG_ASSERT( xSheet.is(), "OCellValueBinding::initialize: NULL sheet, but no exception!" );
616*b1cdbd2cSJim Jagielski 
617*b1cdbd2cSJim Jagielski                 // the concrete cell
618*b1cdbd2cSJim Jagielski                 if ( xSheet.is() )
619*b1cdbd2cSJim Jagielski                 {
620*b1cdbd2cSJim Jagielski                     m_xCell.set(xSheet->getCellByPosition( aAddress.Column, aAddress.Row ));
621*b1cdbd2cSJim Jagielski                     Reference< XCellAddressable > xAddressAccess( m_xCell, UNO_QUERY );
622*b1cdbd2cSJim Jagielski                     DBG_ASSERT( xAddressAccess.is(), "OCellValueBinding::initialize: either NULL cell, or cell without address access!" );
623*b1cdbd2cSJim Jagielski                 }
624*b1cdbd2cSJim Jagielski             }
625*b1cdbd2cSJim Jagielski         }
626*b1cdbd2cSJim Jagielski         catch( const Exception& )
627*b1cdbd2cSJim Jagielski         {
628*b1cdbd2cSJim Jagielski             DBG_ERROR( "OCellValueBinding::initialize: caught an exception while retrieving the cell object!" );
629*b1cdbd2cSJim Jagielski         }
630*b1cdbd2cSJim Jagielski 
631*b1cdbd2cSJim Jagielski         if ( !m_xCell.is() )
632*b1cdbd2cSJim Jagielski             throw Exception();
633*b1cdbd2cSJim Jagielski             // TODO error message
634*b1cdbd2cSJim Jagielski 
635*b1cdbd2cSJim Jagielski         m_xCellText.set(m_xCellText.query( m_xCell ));
636*b1cdbd2cSJim Jagielski 
637*b1cdbd2cSJim Jagielski         Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY );
638*b1cdbd2cSJim Jagielski         if ( xBroadcaster.is() )
639*b1cdbd2cSJim Jagielski         {
640*b1cdbd2cSJim Jagielski             xBroadcaster->addModifyListener( this );
641*b1cdbd2cSJim Jagielski         }
642*b1cdbd2cSJim Jagielski 
643*b1cdbd2cSJim Jagielski         // TODO: add as XEventListener to the cell, so we get notified when it dies,
644*b1cdbd2cSJim Jagielski         // and can dispose ourself then
645*b1cdbd2cSJim Jagielski 
646*b1cdbd2cSJim Jagielski         // TODO: somehow add as listener so we get notified when the address of the cell changes
647*b1cdbd2cSJim Jagielski         // We need to forward this as change in our BoundCell property to our property change listeners
648*b1cdbd2cSJim Jagielski 
649*b1cdbd2cSJim Jagielski         // TODO: be an XModifyBroadcaster, so that changes in our cell can be notified
650*b1cdbd2cSJim Jagielski         // to the BindableValue which is/will be bound to this instance.
651*b1cdbd2cSJim Jagielski 
652*b1cdbd2cSJim Jagielski         m_bInitialized = sal_True;
653*b1cdbd2cSJim Jagielski         // TODO: place your code here
654*b1cdbd2cSJim Jagielski     }
655*b1cdbd2cSJim Jagielski 
656*b1cdbd2cSJim Jagielski 
657*b1cdbd2cSJim Jagielski //.........................................................................
658*b1cdbd2cSJim Jagielski }   // namespace calc
659*b1cdbd2cSJim Jagielski //.........................................................................
660