LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - cellvaluebinding.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 125 256 48.8 %
Date: 2012-08-25 Functions: 20 30 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 99 464 21.3 %

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

Generated by: LCOV version 1.10