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