Updated core
[LibreOffice.git] / toolkit / source / controls / grid / sortablegriddatamodel.cxx
blobd4a218c80172265437e10ab09c522da47f127861
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 .
21 #include "sortablegriddatamodel.hxx"
22 #include "toolkit/helper/servicenames.hxx"
24 #include <com/sun/star/i18n/Collator.hpp>
25 #include <com/sun/star/lang/IllegalArgumentException.hpp>
26 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
28 #include <comphelper/anycompare.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <cppuhelper/typeprovider.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <tools/debug.hxx>
33 #include <vcl/svapp.hxx>
35 #include <set>
37 //......................................................................................................................
38 namespace toolkit
40 //......................................................................................................................
42 using ::com::sun::star::uno::TypeClass;
43 using ::com::sun::star::uno::TypeClass_VOID;
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::XInterface;
46 using ::com::sun::star::uno::UNO_QUERY;
47 using ::com::sun::star::uno::UNO_QUERY_THROW;
48 using ::com::sun::star::uno::UNO_SET_THROW;
49 using ::com::sun::star::uno::Exception;
50 using ::com::sun::star::uno::RuntimeException;
51 using ::com::sun::star::uno::Any;
52 using ::com::sun::star::uno::makeAny;
53 using ::com::sun::star::uno::Sequence;
54 using ::com::sun::star::uno::Type;
55 using ::com::sun::star::uno::XComponentContext;
56 using ::com::sun::star::lang::IndexOutOfBoundsException;
57 using ::com::sun::star::lang::IllegalArgumentException;
58 using ::com::sun::star::awt::grid::XGridDataListener;
59 using ::com::sun::star::beans::Pair;
60 using ::com::sun::star::util::XCloneable;
61 using ::com::sun::star::i18n::XCollator;
62 using ::com::sun::star::i18n::Collator;
63 using ::com::sun::star::lang::XMultiServiceFactory;
64 using ::com::sun::star::awt::grid::GridDataEvent;
65 using ::com::sun::star::lang::EventObject;
66 using ::com::sun::star::ucb::AlreadyInitializedException;
68 #ifdef DBG_UTIL
69 const char* SortableGridDataModel_checkInvariants( const void* _pInstance )
71 return static_cast< const SortableGridDataModel* >( _pInstance )->checkInvariants();
74 //------------------------------------------------------------------------------------------------------------------
75 const char* SortableGridDataModel::checkInvariants() const
77 if ( m_publicToPrivateRowIndex.size() != m_privateToPublicRowIndex.size() )
78 return "inconsistent index maps";
80 if ( m_delegator.is() )
82 if ( m_publicToPrivateRowIndex.size() != size_t( m_delegator->getRowCount() ) )
83 return "wrong cached row count";
85 else
87 if ( !m_publicToPrivateRowIndex.empty() )
88 return "disposed or not initialized, but having a non-empty map";
91 for ( size_t publicIndex=0; publicIndex<m_publicToPrivateRowIndex.size(); ++publicIndex )
93 ::sal_Int32 const privateIndex = m_publicToPrivateRowIndex[ publicIndex ];
94 if ( ( privateIndex < 0 ) || ( size_t( privateIndex ) >= m_privateToPublicRowIndex.size() ) )
95 return "invalid cached private index";
97 if ( m_privateToPublicRowIndex[ privateIndex ] != sal_Int32( publicIndex ) )
98 return "index map traversal not commutavive";
101 if ( impl_isSorted_nothrow() && m_publicToPrivateRowIndex.empty() )
102 return "sorted, but no row index translation tables";
104 if ( !impl_isSorted_nothrow() && !m_publicToPrivateRowIndex.empty() )
105 return "unsorted, but have index translation tables";
107 return NULL;
109 #endif
111 #define DBG_CHECK_ME() \
112 DBG_CHKTHIS( SortableGridDataModel, SortableGridDataModel_checkInvariants )
114 //------------------------------------------------------------------------------------------------------------------
115 namespace
117 template< class STLCONTAINER >
118 static void lcl_clear( STLCONTAINER& i_container )
120 STLCONTAINER empty;
121 empty.swap( i_container );
125 //==================================================================================================================
126 //= SortableGridDataModel
127 //==================================================================================================================
128 DBG_NAME( SortableGridDataModel )
129 //------------------------------------------------------------------------------------------------------------------
130 SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
131 :SortableGridDataModel_Base( m_aMutex )
132 ,SortableGridDataModel_PrivateBase()
133 ,m_xContext( rxContext )
134 ,m_isInitialized( false )
135 ,m_delegator()
136 ,m_collator()
137 ,m_currentSortColumn( -1 )
138 ,m_sortAscending( true )
139 ,m_publicToPrivateRowIndex()
140 ,m_privateToPublicRowIndex()
142 DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
145 //------------------------------------------------------------------------------------------------------------------
146 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
147 :cppu::BaseMutex()
148 ,SortableGridDataModel_Base( m_aMutex )
149 ,SortableGridDataModel_PrivateBase()
150 ,m_xContext( i_copySource.m_xContext )
151 ,m_isInitialized( true )
152 ,m_delegator()
153 ,m_collator( i_copySource.m_collator )
154 ,m_currentSortColumn( i_copySource.m_currentSortColumn )
155 ,m_sortAscending( i_copySource.m_sortAscending )
156 ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
157 ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
159 DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
161 ENSURE_OR_THROW( i_copySource.m_delegator.is(),
162 "not expected to be called for a disposed copy source!" );
163 m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
166 //------------------------------------------------------------------------------------------------------------------
167 SortableGridDataModel::~SortableGridDataModel()
169 if ( !rBHelper.bDisposed )
171 acquire();
172 dispose();
175 DBG_DTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
178 //------------------------------------------------------------------------------------------------------------------
179 Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType ) throw (RuntimeException)
181 Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
182 if ( !aReturn.hasValue() )
183 aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
184 return aReturn;
187 //------------------------------------------------------------------------------------------------------------------
188 void SAL_CALL SortableGridDataModel::acquire( ) throw ()
190 SortableGridDataModel_Base::acquire();
193 //------------------------------------------------------------------------------------------------------------------
194 void SAL_CALL SortableGridDataModel::release( ) throw ()
196 SortableGridDataModel_Base::release();
199 //------------------------------------------------------------------------------------------------------------------
200 Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( ) throw (RuntimeException)
202 return SortableGridDataModel_Base::getTypes();
203 // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
206 //------------------------------------------------------------------------------------------------------------------
207 Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( ) throw (RuntimeException)
209 static ::cppu::OImplementationId aId;
210 return aId.getImplementationId();
213 //------------------------------------------------------------------------------------------------------------------
214 namespace
216 Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
218 Reference< XCollator > const xCollator = Collator::create( rxContext );
219 xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
220 return xCollator;
224 //------------------------------------------------------------------------------------------------------------------
225 void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments ) throw (Exception, RuntimeException)
227 ::comphelper::ComponentGuard aGuard( *this, rBHelper );
228 DBG_CHECK_ME();
230 if ( m_delegator.is() )
231 throw AlreadyInitializedException( OUString(), *this );
233 Reference< XMutableGridDataModel > xDelegator;
234 Reference< XCollator > xCollator;
235 switch ( i_arguments.getLength() )
237 case 1: // SortableGridDataModel.create( XMutableGridDataModel )
238 xDelegator.set( i_arguments[0], UNO_QUERY );
239 xCollator = lcl_loadDefaultCollator_throw( m_xContext );
240 break;
242 case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
243 xDelegator.set( i_arguments[0], UNO_QUERY );
244 xCollator.set( i_arguments[1], UNO_QUERY );
245 if ( !xCollator.is() )
246 throw IllegalArgumentException( OUString(), *this, 2 );
247 break;
249 if ( !xDelegator.is() )
250 throw IllegalArgumentException( OUString(), *this, 1 );
252 m_delegator = xDelegator;
253 m_collator = xCollator;
255 m_delegator->addGridDataListener( this );
257 m_isInitialized = true;
260 //------------------------------------------------------------------------------------------------------------------
261 GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
263 GridDataEvent aEvent( i_originalEvent );
264 aEvent.Source = *const_cast< SortableGridDataModel* >( this );
265 aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
266 aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
267 return aEvent;
270 //------------------------------------------------------------------------------------------------------------------
271 void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
272 GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
274 ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( XGridDataListener::static_type() );
275 if ( pListeners == NULL )
276 return;
278 i_instanceLock.clear();
279 pListeners->notifyEach( i_listenerMethod, i_publicEvent );
282 //------------------------------------------------------------------------------------------------------------------
283 void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event ) throw (RuntimeException)
285 MethodGuard aGuard( *this, rBHelper );
286 DBG_CHECK_ME();
288 if ( impl_isSorted_nothrow() )
290 // no infrastructure is in place currently to sort the new row to its proper location,
291 // so we remove the sorting here.
292 impl_removeColumnSort( aGuard );
293 aGuard.reset();
296 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
297 impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
300 //------------------------------------------------------------------------------------------------------------------
301 namespace
303 void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
305 for ( ::std::vector< ::sal_Int32 >::iterator loop = io_indexMap.begin();
306 loop != io_indexMap.end();
307 ++loop
310 if ( *loop >= i_threshold )
311 --*loop;
316 //------------------------------------------------------------------------------------------------------------------
317 void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
319 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
321 // clear the indexes
322 lcl_clear( m_publicToPrivateRowIndex );
323 lcl_clear( m_privateToPublicRowIndex );
325 // rebuild the index
326 if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
328 impl_removeColumnSort( i_instanceLock );
329 return;
332 // broadcast an artificial event, saying that all rows have been removed
333 GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
334 impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
335 i_instanceLock.reset();
337 // broadcast an artificial event, saying that n rows have been added
338 GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
339 impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
342 //------------------------------------------------------------------------------------------------------------------
343 void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event ) throw (RuntimeException)
345 MethodGuard aGuard( *this, rBHelper );
346 DBG_CHECK_ME();
348 // if the data is not sorted, broadcast the event unchanged
349 if ( !impl_isSorted_nothrow() )
351 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
352 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
353 return;
356 // if all rows have been removed, also simply multiplex to own listeners
357 if ( i_event.FirstRow < 0 )
359 lcl_clear( m_publicToPrivateRowIndex );
360 lcl_clear( m_privateToPublicRowIndex );
361 GridDataEvent aEvent( i_event );
362 aEvent.Source = *this;
363 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
364 return;
367 bool needReIndex = false;
368 if ( i_event.FirstRow != i_event.LastRow )
370 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
371 needReIndex = true;
373 else if ( size_t( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
375 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
376 needReIndex = true;
379 if ( needReIndex )
381 impl_rebuildIndexesAndNotify( aGuard );
382 return;
385 // build public event version
386 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
388 // remove the entries from the index maps
389 sal_Int32 const privateIndex = i_event.FirstRow;
390 sal_Int32 const publicIndex = aEvent.FirstRow;
392 m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
393 m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
395 // adjust remaining entries in the index maps
396 lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
397 lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
399 // broadcast the event
400 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
403 //------------------------------------------------------------------------------------------------------------------
404 void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event ) throw (RuntimeException)
406 MethodGuard aGuard( *this, rBHelper );
407 DBG_CHECK_ME();
409 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
410 impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
413 //------------------------------------------------------------------------------------------------------------------
414 void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event ) throw (RuntimeException)
416 MethodGuard aGuard( *this, rBHelper );
417 DBG_CHECK_ME();
419 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
420 impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
423 //------------------------------------------------------------------------------------------------------------------
424 void SAL_CALL SortableGridDataModel::disposing( const EventObject& i_event ) throw (RuntimeException)
426 // not interested in
427 OSL_UNUSED( i_event );
430 //------------------------------------------------------------------------------------------------------------------
431 namespace
433 class CellDataLessComparison : public ::std::binary_function< sal_Int32, sal_Int32, bool >
435 public:
436 CellDataLessComparison(
437 ::std::vector< Any > const & i_data,
438 ::comphelper::IKeyPredicateLess& i_predicate,
439 sal_Bool const i_sortAscending
441 :m_data( i_data )
442 ,m_predicate( i_predicate )
443 ,m_sortAscending( i_sortAscending )
447 bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
449 Any const & lhs = m_data[ i_lhs ];
450 Any const & rhs = m_data[ i_rhs ];
451 // <VOID/> is less than everything else
452 if ( !lhs.hasValue() )
453 return m_sortAscending;
454 if ( !rhs.hasValue() )
455 return !m_sortAscending;
457 // actually compare
458 if ( m_sortAscending )
459 return m_predicate.isLess( lhs, rhs );
460 else
461 return m_predicate.isLess( rhs, lhs );
464 private:
465 ::std::vector< Any > const & m_data;
466 ::comphelper::IKeyPredicateLess const & m_predicate;
467 sal_Bool const m_sortAscending;
471 //------------------------------------------------------------------------------------------------------------------
472 bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, sal_Bool const i_sortAscending )
474 ::sal_Int32 const rowCount( getRowCount() );
475 ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
479 // build an unsorted translation table, and retrieve the unsorted data
480 ::std::vector< Any > aColumnData( rowCount );
481 Type dataType;
482 for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
484 aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
485 aPublicToPrivate[ rowIndex ] = rowIndex;
487 // determine the data types we assume for the complete column
488 if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
489 dataType = aColumnData[ rowIndex ].getValueType();
492 // get predicate object
493 ::std::auto_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
494 ENSURE_OR_RETURN_FALSE( pPredicate.get(), "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!" );
496 // then sort
497 CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
498 ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
500 catch( const Exception& )
502 DBG_UNHANDLED_EXCEPTION();
503 return false;
506 // also build the "private to public" mapping
507 ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
508 for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
509 aPrivateToPublic[ aPublicToPrivate[i] ] = i;
511 m_publicToPrivateRowIndex.swap( aPublicToPrivate );
512 m_privateToPublicRowIndex.swap( aPrivateToPublic );
514 return true;
517 //------------------------------------------------------------------------------------------------------------------
518 void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, ::sal_Bool i_sortAscending ) throw (IndexOutOfBoundsException, RuntimeException)
520 MethodGuard aGuard( *this, rBHelper );
521 DBG_CHECK_ME();
523 if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
524 throw IndexOutOfBoundsException( OUString(), *this );
526 if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
527 return;
529 m_currentSortColumn = i_columnIndex;
530 m_sortAscending = i_sortAscending;
532 impl_broadcast(
533 &XGridDataListener::dataChanged,
534 GridDataEvent( *this, -1, -1, -1, -1 ),
535 aGuard
539 //------------------------------------------------------------------------------------------------------------------
540 void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
542 lcl_clear( m_publicToPrivateRowIndex );
543 lcl_clear( m_privateToPublicRowIndex );
545 m_currentSortColumn = -1;
546 m_sortAscending = sal_True;
549 //------------------------------------------------------------------------------------------------------------------
550 void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
552 impl_removeColumnSort_noBroadcast();
553 impl_broadcast(
554 &XGridDataListener::dataChanged,
555 GridDataEvent( *this, -1, -1, -1, -1 ),
556 i_instanceLock
560 //------------------------------------------------------------------------------------------------------------------
561 void SAL_CALL SortableGridDataModel::removeColumnSort( ) throw (RuntimeException)
563 MethodGuard aGuard( *this, rBHelper );
564 DBG_CHECK_ME();
565 impl_removeColumnSort( aGuard );
568 //------------------------------------------------------------------------------------------------------------------
569 Pair< ::sal_Int32, ::sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( ) throw (RuntimeException)
571 MethodGuard aGuard( *this, rBHelper );
572 DBG_CHECK_ME();
574 return Pair< ::sal_Int32, ::sal_Bool >( m_currentSortColumn, m_sortAscending );
577 //------------------------------------------------------------------------------------------------------------------
578 void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException)
580 MethodGuard aGuard( *this, rBHelper );
581 DBG_CHECK_ME();
583 Reference< XMutableGridDataModel > const delegator( m_delegator );
584 aGuard.clear();
585 delegator->addRow( i_heading, i_data );
588 //------------------------------------------------------------------------------------------------------------------
589 void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, RuntimeException)
591 MethodGuard aGuard( *this, rBHelper );
592 DBG_CHECK_ME();
594 Reference< XMutableGridDataModel > const delegator( m_delegator );
595 aGuard.clear();
596 delegator->addRows( i_headings, i_data );
599 //------------------------------------------------------------------------------------------------------------------
600 void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException, IndexOutOfBoundsException)
602 MethodGuard aGuard( *this, rBHelper );
603 DBG_CHECK_ME();
605 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
606 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
608 Reference< XMutableGridDataModel > const delegator( m_delegator );
609 aGuard.clear();
610 delegator->insertRow( rowIndex, i_heading, i_data );
613 //------------------------------------------------------------------------------------------------------------------
614 void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, IndexOutOfBoundsException, RuntimeException)
616 MethodGuard aGuard( *this, rBHelper );
617 DBG_CHECK_ME();
619 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
620 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
622 Reference< XMutableGridDataModel > const delegator( m_delegator );
623 aGuard.clear();
624 delegator->insertRows( rowIndex, i_headings, i_data );
627 //------------------------------------------------------------------------------------------------------------------
628 void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
630 MethodGuard aGuard( *this, rBHelper );
631 DBG_CHECK_ME();
633 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
635 Reference< XMutableGridDataModel > const delegator( m_delegator );
636 aGuard.clear();
637 delegator->removeRow( rowIndex );
640 //------------------------------------------------------------------------------------------------------------------
641 void SAL_CALL SortableGridDataModel::removeAllRows( ) throw (RuntimeException)
643 MethodGuard aGuard( *this, rBHelper );
644 DBG_CHECK_ME();
646 Reference< XMutableGridDataModel > const delegator( m_delegator );
647 aGuard.clear();
648 delegator->removeAllRows();
651 //------------------------------------------------------------------------------------------------------------------
652 void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
654 MethodGuard aGuard( *this, rBHelper );
655 DBG_CHECK_ME();
657 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
659 Reference< XMutableGridDataModel > const delegator( m_delegator );
660 aGuard.clear();
661 delegator->updateCellData( i_columnIndex, rowIndex, i_value );
664 //------------------------------------------------------------------------------------------------------------------
665 void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
667 MethodGuard aGuard( *this, rBHelper );
668 DBG_CHECK_ME();
670 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
672 Reference< XMutableGridDataModel > const delegator( m_delegator );
673 aGuard.clear();
674 delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
677 //------------------------------------------------------------------------------------------------------------------
678 void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading ) throw (IndexOutOfBoundsException, RuntimeException)
680 MethodGuard aGuard( *this, rBHelper );
681 DBG_CHECK_ME();
683 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
685 Reference< XMutableGridDataModel > const delegator( m_delegator );
686 aGuard.clear();
687 delegator->updateRowHeading( rowIndex, i_heading );
690 //------------------------------------------------------------------------------------------------------------------
691 void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
693 MethodGuard aGuard( *this, rBHelper );
694 DBG_CHECK_ME();
696 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
698 Reference< XMutableGridDataModel > const delegator( m_delegator );
699 aGuard.clear();
700 delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
703 //------------------------------------------------------------------------------------------------------------------
704 void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
706 MethodGuard aGuard( *this, rBHelper );
707 DBG_CHECK_ME();
709 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
711 Reference< XMutableGridDataModel > const delegator( m_delegator );
712 aGuard.clear();
713 delegator->updateRowToolTip( rowIndex, i_value );
716 //------------------------------------------------------------------------------------------------------------------
717 void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
719 rBHelper.addListener( XGridDataListener::static_type(), i_listener );
722 //------------------------------------------------------------------------------------------------------------------
723 void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
725 rBHelper.removeListener( XGridDataListener::static_type(), i_listener );
728 //------------------------------------------------------------------------------------------------------------------
729 ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount() throw (RuntimeException)
731 MethodGuard aGuard( *this, rBHelper );
732 DBG_CHECK_ME();
734 Reference< XMutableGridDataModel > const delegator( m_delegator );
735 aGuard.clear();
736 return delegator->getRowCount();
739 //------------------------------------------------------------------------------------------------------------------
740 ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount() throw (RuntimeException)
742 MethodGuard aGuard( *this, rBHelper );
743 DBG_CHECK_ME();
745 Reference< XMutableGridDataModel > const delegator( m_delegator );
746 aGuard.clear();
747 return delegator->getColumnCount();
750 //------------------------------------------------------------------------------------------------------------------
751 Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
753 MethodGuard aGuard( *this, rBHelper );
754 DBG_CHECK_ME();
756 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
758 Reference< XMutableGridDataModel > const delegator( m_delegator );
759 aGuard.clear();
760 return delegator->getCellData( i_columnIndex, rowIndex );
763 //------------------------------------------------------------------------------------------------------------------
764 Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
766 MethodGuard aGuard( *this, rBHelper );
767 DBG_CHECK_ME();
769 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
771 Reference< XMutableGridDataModel > const delegator( m_delegator );
772 aGuard.clear();
773 return delegator->getCellToolTip( i_columnIndex, rowIndex );
776 //------------------------------------------------------------------------------------------------------------------
777 Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
779 MethodGuard aGuard( *this, rBHelper );
780 DBG_CHECK_ME();
782 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
784 Reference< XMutableGridDataModel > const delegator( m_delegator );
785 aGuard.clear();
786 return delegator->getRowHeading( rowIndex );
789 //------------------------------------------------------------------------------------------------------------------
790 Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
792 MethodGuard aGuard( *this, rBHelper );
793 DBG_CHECK_ME();
795 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
797 Reference< XMutableGridDataModel > const delegator( m_delegator );
798 aGuard.clear();
799 return delegator->getRowData( rowIndex );
802 //------------------------------------------------------------------------------------------------------------------
803 void SAL_CALL SortableGridDataModel::disposing()
805 m_currentSortColumn = -1;
807 Reference< XComponent > const delegatorComponent( m_delegator.get() );
808 m_delegator->removeGridDataListener( this );
809 m_delegator.clear();
810 delegatorComponent->dispose();
812 Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
813 m_collator.clear();
814 if ( collatorComponent.is() )
815 collatorComponent->dispose();
817 lcl_clear( m_publicToPrivateRowIndex );
818 lcl_clear( m_privateToPublicRowIndex );
821 //------------------------------------------------------------------------------------------------------------------
822 Reference< XCloneable > SAL_CALL SortableGridDataModel::createClone( ) throw (RuntimeException)
824 MethodGuard aGuard( *this, rBHelper );
825 DBG_CHECK_ME();
827 return new SortableGridDataModel( *this );
830 //------------------------------------------------------------------------------------------------------------------
831 OUString SAL_CALL SortableGridDataModel::getImplementationName( ) throw (RuntimeException)
833 return OUString( "org.openoffice.comp.toolkit.SortableGridDataModel" );
836 //------------------------------------------------------------------------------------------------------------------
837 ::sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName ) throw (RuntimeException)
839 Sequence< OUString > const aServiceNames( getSupportedServiceNames() );
840 for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i )
841 if ( aServiceNames[i] == i_serviceName )
842 return sal_True;
843 return sal_False;
846 //------------------------------------------------------------------------------------------------------------------
847 Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( ) throw (RuntimeException)
849 Sequence< OUString > aServiceNames(1);
850 aServiceNames[0] = OUString::createFromAscii( szServiceName_SortableGridDataModel );
851 return aServiceNames;
854 //------------------------------------------------------------------------------------------------------------------
855 ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
857 if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
858 throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
860 if ( !impl_isSorted_nothrow() )
861 // no need to translate anything
862 return i_publicRowIndex;
864 ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
865 "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
866 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
867 // elements
869 return m_publicToPrivateRowIndex[ i_publicRowIndex ];
872 //------------------------------------------------------------------------------------------------------------------
873 ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
875 if ( !impl_isSorted_nothrow() )
876 // no need to translate anything
877 return i_privateRowIndex;
879 if ( i_privateRowIndex < 0 )
880 return i_privateRowIndex;
882 ENSURE_OR_RETURN( size_t( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
883 "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
885 return m_privateToPublicRowIndex[ i_privateRowIndex ];
888 //......................................................................................................................
889 } // namespace toolkit
890 //......................................................................................................................
892 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SortableGridDataModel_CreateInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory )
894 return *( new ::toolkit::SortableGridDataModel( comphelper::getComponentContext(i_factory) ) );
897 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */