sync master with lastest vba changes
[ooovba.git] / sc / source / ui / unoobj / celllistsource.cxx
blob3c03d44ca955e6cab029faeb701d14a730bfe3df
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: celllistsource.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include "celllistsource.hxx"
34 #include <tools/debug.hxx>
35 #include <com/sun/star/text/XTextRange.hpp>
36 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
37 #include <com/sun/star/util/XModifyBroadcaster.hpp>
38 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/beans/NamedValue.hpp>
42 //.........................................................................
43 namespace calc
45 //.........................................................................
47 #define PROP_HANDLE_RANGE_ADDRESS 1
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;
59 //=====================================================================
60 //= OCellListSource
61 //=====================================================================
62 DBG_NAME( OCellListSource )
63 //---------------------------------------------------------------------
64 #ifdef DBG_UTIL
65 const char* OCellListSource::checkConsistency_static( const void* _pThis )
67 return static_cast< const OCellListSource* >( _pThis )->checkConsistency( );
70 const char* OCellListSource::checkConsistency( ) const
72 const char* pAssertion = NULL;
74 // TODO: place any checks here to ensure consistency of this instance
76 return pAssertion;
78 #endif
80 //---------------------------------------------------------------------
81 OCellListSource::OCellListSource( const Reference< XSpreadsheetDocument >& _rxDocument )
82 :OCellListSource_Base( m_aMutex )
83 ,OCellListSource_PBase( OCellListSource_Base::rBHelper )
84 ,m_xDocument( _rxDocument )
85 ,m_aListEntryListeners( m_aMutex )
86 ,m_bInitialized( sal_False )
88 DBG_CTOR( OCellListSource, checkConsistency_static );
90 OSL_PRECOND( m_xDocument.is(), "OCellListSource::OCellListSource: invalid document!" );
92 // register our property at the base class
93 CellRangeAddress aInitialPropValue;
94 registerPropertyNoMember(
95 ::rtl::OUString::createFromAscii( "CellRange" ),
96 PROP_HANDLE_RANGE_ADDRESS,
97 PropertyAttribute::BOUND | PropertyAttribute::READONLY,
98 ::getCppuType( &aInitialPropValue ),
99 &aInitialPropValue
103 //---------------------------------------------------------------------
104 OCellListSource::~OCellListSource( )
106 if ( !OCellListSource_Base::rBHelper.bDisposed )
108 acquire(); // prevent duplicate dtor
109 dispose();
112 DBG_DTOR( OCellListSource, checkConsistency_static );
115 //--------------------------------------------------------------------
116 IMPLEMENT_FORWARD_XINTERFACE2( OCellListSource, OCellListSource_Base, OCellListSource_PBase )
118 //--------------------------------------------------------------------
119 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellListSource, OCellListSource_Base, OCellListSource_PBase )
121 //--------------------------------------------------------------------
122 void SAL_CALL OCellListSource::disposing()
124 ::osl::MutexGuard aGuard( m_aMutex );
125 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
127 Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY );
128 if ( xBroadcaster.is() )
130 xBroadcaster->removeModifyListener( this );
133 EventObject aDisposeEvent( *this );
134 m_aListEntryListeners.disposeAndClear( aDisposeEvent );
136 // OCellListSource_Base::disposing();
137 WeakAggComponentImplHelperBase::disposing();
139 // TODO: clean up here whatever you need to clean up (e.g. revoking listeners etc.)
142 //--------------------------------------------------------------------
143 Reference< XPropertySetInfo > SAL_CALL OCellListSource::getPropertySetInfo( ) throw(RuntimeException)
145 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
146 return createPropertySetInfo( getInfoHelper() ) ;
149 //--------------------------------------------------------------------
150 ::cppu::IPropertyArrayHelper& SAL_CALL OCellListSource::getInfoHelper()
152 return *OCellListSource_PABase::getArrayHelper();
155 //--------------------------------------------------------------------
156 ::cppu::IPropertyArrayHelper* OCellListSource::createArrayHelper( ) const
158 Sequence< Property > aProps;
159 describeProperties( aProps );
160 return new ::cppu::OPropertyArrayHelper(aProps);
163 //--------------------------------------------------------------------
164 void SAL_CALL OCellListSource::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
166 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
167 DBG_ASSERT( _nHandle == PROP_HANDLE_RANGE_ADDRESS, "OCellListSource::getFastPropertyValue: invalid handle!" );
168 // we only have this one property ....
169 (void)_nHandle; // avoid warning in product version
171 _rValue <<= getRangeAddress( );
174 //--------------------------------------------------------------------
175 void OCellListSource::checkDisposed( ) const SAL_THROW( ( DisposedException ) )
177 if ( OCellListSource_Base::rBHelper.bInDispose || OCellListSource_Base::rBHelper.bDisposed )
178 throw DisposedException();
179 // TODO: is it worth having an error message here?
182 //--------------------------------------------------------------------
183 void OCellListSource::checkInitialized() SAL_THROW( ( RuntimeException ) )
185 if ( !m_bInitialized )
186 throw RuntimeException();
187 // TODO: error message
190 //--------------------------------------------------------------------
191 ::rtl::OUString SAL_CALL OCellListSource::getImplementationName( ) throw (RuntimeException)
193 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sheet.OCellListSource" ) );
196 //--------------------------------------------------------------------
197 sal_Bool SAL_CALL OCellListSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
199 Sequence< ::rtl::OUString > aSupportedServices( getSupportedServiceNames() );
200 const ::rtl::OUString* pLookup = aSupportedServices.getConstArray();
201 const ::rtl::OUString* pLookupEnd = aSupportedServices.getConstArray() + aSupportedServices.getLength();
202 while ( pLookup != pLookupEnd )
203 if ( *pLookup++ == _rServiceName )
204 return sal_True;
206 return sal_False;
209 //--------------------------------------------------------------------
210 Sequence< ::rtl::OUString > SAL_CALL OCellListSource::getSupportedServiceNames( ) throw (RuntimeException)
212 Sequence< ::rtl::OUString > aServices( 2 );
213 aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.CellRangeListSource" ) );
214 aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.binding.ListEntrySource" ) );
215 return aServices;
218 //--------------------------------------------------------------------
219 CellRangeAddress OCellListSource::getRangeAddress( ) const
221 OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" );
223 CellRangeAddress aAddress;
224 Reference< XCellRangeAddressable > xRangeAddress( m_xRange, UNO_QUERY );
225 if ( xRangeAddress.is() )
226 aAddress = xRangeAddress->getRangeAddress( );
227 return aAddress;
230 //--------------------------------------------------------------------
231 ::rtl::OUString OCellListSource::getCellTextContent_noCheck( sal_Int32 _nRangeRelativeColumn, sal_Int32 _nRangeRelativeRow )
233 OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" );
234 Reference< XTextRange > xCellText;
235 if ( m_xRange.is() )
236 xCellText.set(xCellText.query( m_xRange->getCellByPosition( _nRangeRelativeColumn, _nRangeRelativeRow ) ));
238 ::rtl::OUString sText;
239 if ( xCellText.is() )
240 sText = xCellText->getString();
241 return sText;
244 //--------------------------------------------------------------------
245 sal_Int32 SAL_CALL OCellListSource::getListEntryCount( ) throw (RuntimeException)
247 ::osl::MutexGuard aGuard( m_aMutex );
248 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
249 checkDisposed();
250 checkInitialized();
252 CellRangeAddress aAddress( getRangeAddress( ) );
253 return aAddress.EndRow - aAddress.StartRow + 1;
256 //--------------------------------------------------------------------
257 ::rtl::OUString SAL_CALL OCellListSource::getListEntry( sal_Int32 _nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
259 ::osl::MutexGuard aGuard( m_aMutex );
260 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
261 checkDisposed();
262 checkInitialized();
264 if ( _nPosition >= getListEntryCount() )
265 throw IndexOutOfBoundsException();
267 return getCellTextContent_noCheck( 0, _nPosition );
270 //--------------------------------------------------------------------
271 Sequence< ::rtl::OUString > SAL_CALL OCellListSource::getAllListEntries( ) throw (RuntimeException)
273 ::osl::MutexGuard aGuard( m_aMutex );
274 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
275 checkDisposed();
276 checkInitialized();
278 Sequence< ::rtl::OUString > aAllEntries( getListEntryCount() );
279 ::rtl::OUString* pAllEntries = aAllEntries.getArray();
280 for ( sal_Int32 i = 0; i < aAllEntries.getLength(); ++i )
282 *pAllEntries++ = getCellTextContent_noCheck( 0, i );
285 return aAllEntries;
288 //--------------------------------------------------------------------
289 void SAL_CALL OCellListSource::addListEntryListener( const Reference< XListEntryListener >& _rxListener ) throw (NullPointerException, RuntimeException)
291 ::osl::MutexGuard aGuard( m_aMutex );
292 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
293 checkDisposed();
294 checkInitialized();
296 if ( !_rxListener.is() )
297 throw NullPointerException();
299 m_aListEntryListeners.addInterface( _rxListener );
302 //--------------------------------------------------------------------
303 void SAL_CALL OCellListSource::removeListEntryListener( const Reference< XListEntryListener >& _rxListener ) throw (NullPointerException, RuntimeException)
305 ::osl::MutexGuard aGuard( m_aMutex );
306 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
307 checkDisposed();
308 checkInitialized();
310 if ( !_rxListener.is() )
311 throw NullPointerException();
313 m_aListEntryListeners.removeInterface( _rxListener );
316 //--------------------------------------------------------------------
317 void SAL_CALL OCellListSource::modified( const EventObject& /* aEvent */ ) throw (RuntimeException)
319 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
321 notifyModified();
324 //--------------------------------------------------------------------
325 void OCellListSource::notifyModified()
327 EventObject aEvent;
328 aEvent.Source.set(*this);
330 ::cppu::OInterfaceIteratorHelper aIter( m_aListEntryListeners );
331 while ( aIter.hasMoreElements() )
335 static_cast< XListEntryListener* >( aIter.next() )->allEntriesChanged( aEvent );
337 catch( const RuntimeException& )
339 // silent this
341 catch( const Exception& )
343 DBG_ERROR( "OCellListSource::notifyModified: caught a (non-runtime) exception!" );
349 //--------------------------------------------------------------------
350 void SAL_CALL OCellListSource::disposing( const EventObject& aEvent ) throw (RuntimeException)
352 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
354 Reference<XInterface> xRangeInt( m_xRange, UNO_QUERY );
355 if ( xRangeInt == aEvent.Source )
357 // release references to range object
358 m_xRange.clear();
362 //--------------------------------------------------------------------
363 void SAL_CALL OCellListSource::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
365 if ( m_bInitialized )
366 throw Exception();
367 // TODO: error message
369 // get the cell address
370 CellRangeAddress aRangeAddress;
371 sal_Bool bFoundAddress = sal_False;
373 const Any* pLoop = _rArguments.getConstArray();
374 const Any* pLoopEnd = _rArguments.getConstArray() + _rArguments.getLength();
375 for ( ; ( pLoop != pLoopEnd ) && !bFoundAddress; ++pLoop )
377 NamedValue aValue;
378 if ( *pLoop >>= aValue )
380 if ( aValue.Name.equalsAscii( "CellRange" ) )
382 if ( aValue.Value >>= aRangeAddress )
383 bFoundAddress = sal_True;
388 if ( !bFoundAddress )
389 // TODO: error message
390 throw Exception();
392 // determine the range we're bound to
395 if ( m_xDocument.is() )
397 // first the sheets collection
398 Reference< XIndexAccess > xSheets(m_xDocument->getSheets( ), UNO_QUERY);
399 DBG_ASSERT( xSheets.is(), "OCellListSource::initialize: could not retrieve the sheets!" );
401 if ( xSheets.is() )
403 // the concrete sheet
404 Reference< XCellRange > xSheet(xSheets->getByIndex( aRangeAddress.Sheet ), UNO_QUERY);
405 DBG_ASSERT( xSheet.is(), "OCellListSource::initialize: NULL sheet, but no exception!" );
407 // the concrete cell
408 if ( xSheet.is() )
410 m_xRange.set(xSheet->getCellRangeByPosition(
411 aRangeAddress.StartColumn, aRangeAddress.StartRow,
412 aRangeAddress.EndColumn, aRangeAddress.EndRow));
413 DBG_ASSERT( Reference< XCellRangeAddressable >( m_xRange, UNO_QUERY ).is(), "OCellListSource::initialize: either NULL range, or cell without address access!" );
418 catch( const Exception& )
420 DBG_ERROR( "OCellListSource::initialize: caught an exception while retrieving the cell object!" );
424 if ( !m_xRange.is() )
425 throw Exception();
426 // TODO error message
428 Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY );
429 if ( xBroadcaster.is() )
431 xBroadcaster->addModifyListener( this );
434 // TODO: add as XEventListener to the cell range, so we get notified when it dies,
435 // and can dispose ourself then
437 // TODO: somehow add as listener so we get notified when the address of the cell range changes
438 // We need to forward this as change in our CellRange property to our property change listeners
440 // TODO: somehow add as listener to the cells in the range, so that we get notified
441 // when their content changes. We need to forward this to our list entry listeners then
443 // TODO: somehow add as listener so that we get notified of insertions and removals of rows in our
444 // range. In this case, we need to fire a change in our CellRange property, and additionally
445 // notify our XListEntryListeners
447 m_bInitialized = sal_True;
450 //.........................................................................
451 } // namespace calc
452 //.........................................................................