LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - cellvaluebinding.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 121 250 48.4 %
Date: 2014-11-03 Functions: 20 30 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10