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