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

Generated by: LCOV version 1.10