Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / unoobj / celllistsource.cxx
blob468d48709da544a5093ff8fff76a38c6bc8451ad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "celllistsource.hxx"
21 #include <tools/debug.hxx>
22 #include <com/sun/star/text/XTextRange.hpp>
23 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
24 #include <com/sun/star/util/XModifyBroadcaster.hpp>
25 #include <com/sun/star/container/XIndexAccess.hpp>
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <com/sun/star/beans/NamedValue.hpp>
29 //.........................................................................
30 namespace calc
32 //.........................................................................
34 #define PROP_HANDLE_RANGE_ADDRESS 1
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::lang;
38 using namespace ::com::sun::star::table;
39 using namespace ::com::sun::star::text;
40 using namespace ::com::sun::star::sheet;
41 using namespace ::com::sun::star::container;
42 using namespace ::com::sun::star::beans;
43 using namespace ::com::sun::star::util;
44 using namespace ::com::sun::star::form::binding;
46 //=====================================================================
47 //= OCellListSource
48 //=====================================================================
49 DBG_NAME( OCellListSource )
50 //---------------------------------------------------------------------
51 #ifdef DBG_UTIL
52 const char* OCellListSource::checkConsistency_static( const void* _pThis )
54 return static_cast< const OCellListSource* >( _pThis )->checkConsistency( );
57 const char* OCellListSource::checkConsistency( ) const
59 const char* pAssertion = NULL;
61 // TODO: place any checks here to ensure consistency of this instance
63 return pAssertion;
65 #endif
67 //---------------------------------------------------------------------
68 OCellListSource::OCellListSource( const Reference< XSpreadsheetDocument >& _rxDocument )
69 :OCellListSource_Base( m_aMutex )
70 ,OCellListSource_PBase( OCellListSource_Base::rBHelper )
71 ,m_xDocument( _rxDocument )
72 ,m_aListEntryListeners( m_aMutex )
73 ,m_bInitialized( false )
75 DBG_CTOR( OCellListSource, checkConsistency_static );
77 OSL_PRECOND( m_xDocument.is(), "OCellListSource::OCellListSource: invalid document!" );
79 // register our property at the base class
80 CellRangeAddress aInitialPropValue;
81 registerPropertyNoMember(
82 OUString( "CellRange" ),
83 PROP_HANDLE_RANGE_ADDRESS,
84 PropertyAttribute::BOUND | PropertyAttribute::READONLY,
85 ::getCppuType( &aInitialPropValue ),
86 &aInitialPropValue
90 //---------------------------------------------------------------------
91 OCellListSource::~OCellListSource( )
93 if ( !OCellListSource_Base::rBHelper.bDisposed )
95 acquire(); // prevent duplicate dtor
96 dispose();
99 DBG_DTOR( OCellListSource, checkConsistency_static );
102 //--------------------------------------------------------------------
103 IMPLEMENT_FORWARD_XINTERFACE2( OCellListSource, OCellListSource_Base, OCellListSource_PBase )
105 //--------------------------------------------------------------------
106 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellListSource, OCellListSource_Base, OCellListSource_PBase )
108 //--------------------------------------------------------------------
109 void SAL_CALL OCellListSource::disposing()
111 ::osl::MutexGuard aGuard( m_aMutex );
112 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
114 Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY );
115 if ( xBroadcaster.is() )
117 xBroadcaster->removeModifyListener( this );
120 EventObject aDisposeEvent( *this );
121 m_aListEntryListeners.disposeAndClear( aDisposeEvent );
123 WeakAggComponentImplHelperBase::disposing();
125 // TODO: clean up here whatever you need to clean up (e.g. revoking listeners etc.)
128 //--------------------------------------------------------------------
129 Reference< XPropertySetInfo > SAL_CALL OCellListSource::getPropertySetInfo( ) throw(RuntimeException)
131 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
132 return createPropertySetInfo( getInfoHelper() ) ;
135 //--------------------------------------------------------------------
136 ::cppu::IPropertyArrayHelper& SAL_CALL OCellListSource::getInfoHelper()
138 return *OCellListSource_PABase::getArrayHelper();
141 //--------------------------------------------------------------------
142 ::cppu::IPropertyArrayHelper* OCellListSource::createArrayHelper( ) const
144 Sequence< Property > aProps;
145 describeProperties( aProps );
146 return new ::cppu::OPropertyArrayHelper(aProps);
149 //--------------------------------------------------------------------
150 void SAL_CALL OCellListSource::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
152 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
153 OSL_ENSURE( _nHandle == PROP_HANDLE_RANGE_ADDRESS, "OCellListSource::getFastPropertyValue: invalid handle!" );
154 // we only have this one property ....
155 (void)_nHandle; // avoid warning in product version
157 _rValue <<= getRangeAddress( );
160 //--------------------------------------------------------------------
161 void OCellListSource::checkDisposed( ) const SAL_THROW( ( DisposedException ) )
163 if ( OCellListSource_Base::rBHelper.bInDispose || OCellListSource_Base::rBHelper.bDisposed )
164 throw DisposedException();
165 // TODO: is it worth having an error message here?
168 //--------------------------------------------------------------------
169 void OCellListSource::checkInitialized() SAL_THROW( ( RuntimeException ) )
171 if ( !m_bInitialized )
172 throw RuntimeException();
173 // TODO: error message
176 //--------------------------------------------------------------------
177 OUString SAL_CALL OCellListSource::getImplementationName( ) throw (RuntimeException)
179 return OUString( "com.sun.star.comp.sheet.OCellListSource" );
182 //--------------------------------------------------------------------
183 sal_Bool SAL_CALL OCellListSource::supportsService( const OUString& _rServiceName ) throw (RuntimeException)
185 Sequence< OUString > aSupportedServices( getSupportedServiceNames() );
186 const OUString* pLookup = aSupportedServices.getConstArray();
187 const OUString* pLookupEnd = aSupportedServices.getConstArray() + aSupportedServices.getLength();
188 while ( pLookup != pLookupEnd )
189 if ( *pLookup++ == _rServiceName )
190 return sal_True;
192 return false;
195 //--------------------------------------------------------------------
196 Sequence< OUString > SAL_CALL OCellListSource::getSupportedServiceNames( ) throw (RuntimeException)
198 Sequence< OUString > aServices( 2 );
199 aServices[ 0 ] = "com.sun.star.table.CellRangeListSource";
200 aServices[ 1 ] = "com.sun.star.form.binding.ListEntrySource";
201 return aServices;
204 //--------------------------------------------------------------------
205 CellRangeAddress OCellListSource::getRangeAddress( ) const
207 OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" );
209 CellRangeAddress aAddress;
210 Reference< XCellRangeAddressable > xRangeAddress( m_xRange, UNO_QUERY );
211 if ( xRangeAddress.is() )
212 aAddress = xRangeAddress->getRangeAddress( );
213 return aAddress;
216 //--------------------------------------------------------------------
217 OUString OCellListSource::getCellTextContent_noCheck( sal_Int32 _nRangeRelativeColumn, sal_Int32 _nRangeRelativeRow )
219 OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" );
220 Reference< XTextRange > xCellText;
221 if ( m_xRange.is() )
222 xCellText.set(xCellText.query( m_xRange->getCellByPosition( _nRangeRelativeColumn, _nRangeRelativeRow ) ));
224 OUString sText;
225 if ( xCellText.is() )
226 sText = xCellText->getString();
227 return sText;
230 //--------------------------------------------------------------------
231 sal_Int32 SAL_CALL OCellListSource::getListEntryCount( ) throw (RuntimeException)
233 ::osl::MutexGuard aGuard( m_aMutex );
234 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
235 checkDisposed();
236 checkInitialized();
238 CellRangeAddress aAddress( getRangeAddress( ) );
239 return aAddress.EndRow - aAddress.StartRow + 1;
242 //--------------------------------------------------------------------
243 OUString SAL_CALL OCellListSource::getListEntry( sal_Int32 _nPosition ) throw (IndexOutOfBoundsException, RuntimeException)
245 ::osl::MutexGuard aGuard( m_aMutex );
246 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
247 checkDisposed();
248 checkInitialized();
250 if ( _nPosition >= getListEntryCount() )
251 throw IndexOutOfBoundsException();
253 return getCellTextContent_noCheck( 0, _nPosition );
256 //--------------------------------------------------------------------
257 Sequence< OUString > SAL_CALL OCellListSource::getAllListEntries( ) throw (RuntimeException)
259 ::osl::MutexGuard aGuard( m_aMutex );
260 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
261 checkDisposed();
262 checkInitialized();
264 Sequence< OUString > aAllEntries( getListEntryCount() );
265 OUString* pAllEntries = aAllEntries.getArray();
266 for ( sal_Int32 i = 0; i < aAllEntries.getLength(); ++i )
268 *pAllEntries++ = getCellTextContent_noCheck( 0, i );
271 return aAllEntries;
274 //--------------------------------------------------------------------
275 void SAL_CALL OCellListSource::addListEntryListener( const Reference< XListEntryListener >& _rxListener ) throw (NullPointerException, RuntimeException)
277 ::osl::MutexGuard aGuard( m_aMutex );
278 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
279 checkDisposed();
280 checkInitialized();
282 if ( !_rxListener.is() )
283 throw NullPointerException();
285 m_aListEntryListeners.addInterface( _rxListener );
288 //--------------------------------------------------------------------
289 void SAL_CALL OCellListSource::removeListEntryListener( 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.removeInterface( _rxListener );
302 //--------------------------------------------------------------------
303 void SAL_CALL OCellListSource::modified( const EventObject& /* aEvent */ ) throw (RuntimeException)
305 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
307 notifyModified();
310 //--------------------------------------------------------------------
311 void OCellListSource::notifyModified()
313 EventObject aEvent;
314 aEvent.Source.set(*this);
316 ::cppu::OInterfaceIteratorHelper aIter( m_aListEntryListeners );
317 while ( aIter.hasMoreElements() )
321 static_cast< XListEntryListener* >( aIter.next() )->allEntriesChanged( aEvent );
323 catch( const RuntimeException& )
325 // silent this
327 catch( const Exception& )
329 OSL_FAIL( "OCellListSource::notifyModified: caught a (non-runtime) exception!" );
335 //--------------------------------------------------------------------
336 void SAL_CALL OCellListSource::disposing( const EventObject& aEvent ) throw (RuntimeException)
338 DBG_CHKTHIS( OCellListSource, checkConsistency_static );
340 Reference<XInterface> xRangeInt( m_xRange, UNO_QUERY );
341 if ( xRangeInt == aEvent.Source )
343 // release references to range object
344 m_xRange.clear();
348 //--------------------------------------------------------------------
349 void SAL_CALL OCellListSource::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
351 if ( m_bInitialized )
352 throw Exception();
353 // TODO: error message
355 // get the cell address
356 CellRangeAddress aRangeAddress;
357 sal_Bool bFoundAddress = false;
359 const Any* pLoop = _rArguments.getConstArray();
360 const Any* pLoopEnd = _rArguments.getConstArray() + _rArguments.getLength();
361 for ( ; ( pLoop != pLoopEnd ) && !bFoundAddress; ++pLoop )
363 NamedValue aValue;
364 if ( *pLoop >>= aValue )
366 if ( aValue.Name == "CellRange" )
368 if ( aValue.Value >>= aRangeAddress )
369 bFoundAddress = sal_True;
374 if ( !bFoundAddress )
375 // TODO: error message
376 throw Exception();
378 // determine the range we're bound to
381 if ( m_xDocument.is() )
383 // first the sheets collection
384 Reference< XIndexAccess > xSheets(m_xDocument->getSheets( ), UNO_QUERY);
385 OSL_ENSURE( xSheets.is(), "OCellListSource::initialize: could not retrieve the sheets!" );
387 if ( xSheets.is() )
389 // the concrete sheet
390 Reference< XCellRange > xSheet(xSheets->getByIndex( aRangeAddress.Sheet ), UNO_QUERY);
391 OSL_ENSURE( xSheet.is(), "OCellListSource::initialize: NULL sheet, but no exception!" );
393 // the concrete cell
394 if ( xSheet.is() )
396 m_xRange.set(xSheet->getCellRangeByPosition(
397 aRangeAddress.StartColumn, aRangeAddress.StartRow,
398 aRangeAddress.EndColumn, aRangeAddress.EndRow));
399 OSL_ENSURE( Reference< XCellRangeAddressable >( m_xRange, UNO_QUERY ).is(), "OCellListSource::initialize: either NULL range, or cell without address access!" );
404 catch( const Exception& )
406 OSL_FAIL( "OCellListSource::initialize: caught an exception while retrieving the cell object!" );
410 if ( !m_xRange.is() )
411 throw Exception();
412 // TODO error message
414 Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY );
415 if ( xBroadcaster.is() )
417 xBroadcaster->addModifyListener( this );
420 // TODO: add as XEventListener to the cell range, so we get notified when it dies,
421 // and can dispose ourself then
423 // TODO: somehow add as listener so we get notified when the address of the cell range changes
424 // We need to forward this as change in our CellRange property to our property change listeners
426 // TODO: somehow add as listener to the cells in the range, so that we get notified
427 // when their content changes. We need to forward this to our list entry listeners then
429 // TODO: somehow add as listener so that we get notified of insertions and removals of rows in our
430 // range. In this case, we need to fire a change in our CellRange property, and additionally
431 // notify our XListEntryListeners
433 m_bInitialized = sal_True;
436 //.........................................................................
437 } // namespace calc
438 //.........................................................................
440 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */