Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / toolkit / source / controls / grid / sortablegriddatamodel.cxx
blob91fc53f1ef950c74077af4a617f49bd847a8cb95
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 <memory>
21 #include <com/sun/star/i18n/Collator.hpp>
22 #include <com/sun/star/i18n/XCollator.hpp>
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <com/sun/star/lang/XInitialization.hpp>
26 #include <com/sun/star/lang/XServiceInfo.hpp>
27 #include <com/sun/star/lang/NotInitializedException.hpp>
28 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <com/sun/star/awt/grid/XGridDataListener.hpp>
31 #include <com/sun/star/awt/grid/XSortableMutableGridDataModel.hpp>
33 #include <cppuhelper/basemutex.hxx>
34 #include <cppuhelper/compbase.hxx>
35 #include <cppuhelper/implbase1.hxx>
36 #include <comphelper/anycompare.hxx>
37 #include <comphelper/componentguard.hxx>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <tools/diagnose_ex.h>
41 #include <vcl/svapp.hxx>
42 #include <vcl/settings.hxx>
44 using namespace css::awt;
45 using namespace css::awt::grid;
46 using namespace css::i18n;
47 using namespace css::lang;
48 using namespace css::ucb;
49 using namespace css::uno;
51 namespace {
53 class SortableGridDataModel;
54 class MethodGuard;
56 typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XSortableMutableGridDataModel
57 , css::lang::XServiceInfo
58 , css::lang::XInitialization
59 > SortableGridDataModel_Base;
60 typedef ::cppu::ImplHelper1 < css::awt::grid::XGridDataListener
61 > SortableGridDataModel_PrivateBase;
62 class SortableGridDataModel :public ::cppu::BaseMutex
63 ,public SortableGridDataModel_Base
64 ,public SortableGridDataModel_PrivateBase
66 public:
67 explicit SortableGridDataModel( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
68 SortableGridDataModel( SortableGridDataModel const & i_copySource );
70 bool isInitialized() const { return m_isInitialized; }
72 protected:
73 virtual ~SortableGridDataModel() override;
75 public:
76 // XSortableGridData
77 virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, sal_Bool SortAscending ) override;
78 virtual void SAL_CALL removeColumnSort( ) override;
79 virtual css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL getCurrentSortOrder( ) override;
81 // XMutableGridDataModel
82 virtual void SAL_CALL addRow( const css::uno::Any& Heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
83 virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any >& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
84 virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
85 virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
86 virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
87 virtual void SAL_CALL removeAllRows( ) override;
88 virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
89 virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
90 virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
91 virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
92 virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
93 virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
94 virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
96 // XGridDataModel
97 virtual ::sal_Int32 SAL_CALL getRowCount() override;
98 virtual ::sal_Int32 SAL_CALL getColumnCount() override;
99 virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
100 virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
101 virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
102 virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
104 // OComponentHelper
105 virtual void SAL_CALL disposing() override;
107 // XCloneable
108 virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
110 // XServiceInfo
111 virtual OUString SAL_CALL getImplementationName( ) override;
112 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
113 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
115 // XInitialization
116 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
118 // XGridDataListener
119 virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
120 virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
121 virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
122 virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
124 // XEventListener
125 virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
127 // XInterface
128 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
129 virtual void SAL_CALL acquire( ) throw () final override;
130 virtual void SAL_CALL release( ) throw () override;
132 // XTypeProvider
133 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
134 virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getImplementationId( ) override;
136 private:
137 /** translates the given public index into one to be passed to our delegator
138 @throws css::lang::IndexOutOfBoundsException
139 if the given index does not denote a valid row
141 ::sal_Int32 impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const;
143 /** translates the given private row index to a public one
145 ::sal_Int32 impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const;
147 bool impl_isSorted_nothrow() const
149 return m_currentSortColumn >= 0;
152 /** rebuilds the index translation structure.
154 Neither <member>m_currentSortColumn</member> nor <member>m_sortAscending</member> are touched by this method.
155 Also, the given column index is not checked, this is the responsibility of the caller.
157 bool impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending );
159 /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
160 clients.
162 css::awt::grid::GridDataEvent
163 impl_createPublicEvent( css::awt::grid::GridDataEvent const & i_originalEvent ) const;
165 /** broadcasts the given event to our registered XGridDataListeners
167 void impl_broadcast(
168 void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( const css::awt::grid::GridDataEvent & ),
169 css::awt::grid::GridDataEvent const & i_publicEvent,
170 MethodGuard& i_instanceLock
173 /** rebuilds our indexes, notifying row removal and row addition events
175 First, a rowsRemoved event is notified to our registered listeners. Then, the index translation tables are
176 rebuilt, and a rowsInserted event is notified.
178 Only to be called when we're sorted.
180 void impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock );
182 /** removes the current sorting, and notifies a change of all data
184 void impl_removeColumnSort( MethodGuard& i_instanceLock );
186 /** removes the current sorting, without any broadcast
188 void impl_removeColumnSort_noBroadcast();
190 private:
191 css::uno::Reference< css::uno::XComponentContext > m_xContext;
192 bool m_isInitialized;
193 css::uno::Reference< css::awt::grid::XMutableGridDataModel > m_delegator;
194 css::uno::Reference< css::i18n::XCollator > m_collator;
195 ::sal_Int32 m_currentSortColumn;
196 bool m_sortAscending;
197 ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
198 ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
201 class MethodGuard : public ::comphelper::ComponentGuard
203 public:
204 MethodGuard( SortableGridDataModel& i_component, ::cppu::OBroadcastHelper & i_broadcastHelper )
205 :comphelper::ComponentGuard( i_component, i_broadcastHelper )
207 if ( !i_component.isInitialized() )
208 throw css::lang::NotInitializedException( OUString(), *&i_component );
212 namespace
214 template< class STLCONTAINER >
215 void lcl_clear( STLCONTAINER& i_container )
217 STLCONTAINER empty;
218 empty.swap( i_container );
222 SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
223 :SortableGridDataModel_Base( m_aMutex )
224 ,SortableGridDataModel_PrivateBase()
225 ,m_xContext( rxContext )
226 ,m_isInitialized( false )
227 ,m_delegator()
228 ,m_collator()
229 ,m_currentSortColumn( -1 )
230 ,m_sortAscending( true )
231 ,m_publicToPrivateRowIndex()
232 ,m_privateToPublicRowIndex()
237 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
238 :cppu::BaseMutex()
239 ,SortableGridDataModel_Base( m_aMutex )
240 ,SortableGridDataModel_PrivateBase()
241 ,m_xContext( i_copySource.m_xContext )
242 ,m_isInitialized( true )
243 ,m_delegator()
244 ,m_collator( i_copySource.m_collator )
245 ,m_currentSortColumn( i_copySource.m_currentSortColumn )
246 ,m_sortAscending( i_copySource.m_sortAscending )
247 ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
248 ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
250 ENSURE_OR_THROW( i_copySource.m_delegator.is(),
251 "not expected to be called for a disposed copy source!" );
252 m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
256 SortableGridDataModel::~SortableGridDataModel()
258 if ( !rBHelper.bDisposed )
260 acquire();
261 dispose();
266 Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType )
268 Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
269 if ( !aReturn.hasValue() )
270 aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
271 return aReturn;
275 void SAL_CALL SortableGridDataModel::acquire( ) throw ()
277 SortableGridDataModel_Base::acquire();
281 void SAL_CALL SortableGridDataModel::release( ) throw ()
283 SortableGridDataModel_Base::release();
287 Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( )
289 return SortableGridDataModel_Base::getTypes();
290 // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
294 Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( )
296 return css::uno::Sequence<sal_Int8>();
300 namespace
302 Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
304 Reference< XCollator > const xCollator = Collator::create( rxContext );
305 xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
306 return xCollator;
311 void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments )
313 ::comphelper::ComponentGuard aGuard( *this, rBHelper );
315 if ( m_delegator.is() )
316 throw AlreadyInitializedException( OUString(), *this );
318 Reference< XMutableGridDataModel > xDelegator;
319 Reference< XCollator > xCollator;
320 switch ( i_arguments.getLength() )
322 case 1: // SortableGridDataModel.create( XMutableGridDataModel )
323 xDelegator.set( i_arguments[0], UNO_QUERY );
324 xCollator = lcl_loadDefaultCollator_throw( m_xContext );
325 break;
327 case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
328 xDelegator.set( i_arguments[0], UNO_QUERY );
329 xCollator.set( i_arguments[1], UNO_QUERY );
330 if ( !xCollator.is() )
331 throw IllegalArgumentException( OUString(), *this, 2 );
332 break;
334 if ( !xDelegator.is() )
335 throw IllegalArgumentException( OUString(), *this, 1 );
337 m_delegator = xDelegator;
338 m_collator = xCollator;
340 m_delegator->addGridDataListener( this );
342 m_isInitialized = true;
346 GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
348 GridDataEvent aEvent( i_originalEvent );
349 aEvent.Source = *const_cast< SortableGridDataModel* >( this );
350 aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
351 aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
352 return aEvent;
356 void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
357 GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
359 ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( cppu::UnoType<XGridDataListener>::get() );
360 if ( pListeners == nullptr )
361 return;
363 i_instanceLock.clear();
364 pListeners->notifyEach( i_listenerMethod, i_publicEvent );
368 void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event )
370 MethodGuard aGuard( *this, rBHelper );
372 if ( impl_isSorted_nothrow() )
374 // no infrastructure is in place currently to sort the new row to its proper location,
375 // so we remove the sorting here.
376 impl_removeColumnSort( aGuard );
377 aGuard.reset();
380 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
381 impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
385 namespace
387 void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
389 for ( ::std::vector< ::sal_Int32 >::iterator loop = io_indexMap.begin();
390 loop != io_indexMap.end();
391 ++loop
394 if ( *loop >= i_threshold )
395 --*loop;
401 void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
403 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
405 // clear the indexes
406 lcl_clear( m_publicToPrivateRowIndex );
407 lcl_clear( m_privateToPublicRowIndex );
409 // rebuild the index
410 if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
412 impl_removeColumnSort( i_instanceLock );
413 return;
416 // broadcast an artificial event, saying that all rows have been removed
417 GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
418 impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
419 i_instanceLock.reset();
421 // broadcast an artificial event, saying that n rows have been added
422 GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
423 impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
427 void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event )
429 MethodGuard aGuard( *this, rBHelper );
431 // if the data is not sorted, broadcast the event unchanged
432 if ( !impl_isSorted_nothrow() )
434 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
435 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
436 return;
439 // if all rows have been removed, also simply multiplex to own listeners
440 if ( i_event.FirstRow < 0 )
442 lcl_clear( m_publicToPrivateRowIndex );
443 lcl_clear( m_privateToPublicRowIndex );
444 GridDataEvent aEvent( i_event );
445 aEvent.Source = *this;
446 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
447 return;
450 bool needReIndex = false;
451 if ( i_event.FirstRow != i_event.LastRow )
453 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
454 needReIndex = true;
456 else if ( size_t( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
458 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
459 needReIndex = true;
462 if ( needReIndex )
464 impl_rebuildIndexesAndNotify( aGuard );
465 return;
468 // build public event version
469 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
471 // remove the entries from the index maps
472 sal_Int32 const privateIndex = i_event.FirstRow;
473 sal_Int32 const publicIndex = aEvent.FirstRow;
475 m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
476 m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
478 // adjust remaining entries in the index maps
479 lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
480 lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
482 // broadcast the event
483 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
487 void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event )
489 MethodGuard aGuard( *this, rBHelper );
491 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
492 impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
496 void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event )
498 MethodGuard aGuard( *this, rBHelper );
500 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
501 impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
505 void SAL_CALL SortableGridDataModel::disposing( const EventObject& )
510 namespace
512 class CellDataLessComparison : public ::std::binary_function< sal_Int32, sal_Int32, bool >
514 public:
515 CellDataLessComparison(
516 ::std::vector< Any > const & i_data,
517 ::comphelper::IKeyPredicateLess& i_predicate,
518 bool const i_sortAscending
520 :m_data( i_data )
521 ,m_predicate( i_predicate )
522 ,m_sortAscending( i_sortAscending )
526 bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
528 Any const & lhs = m_data[ i_lhs ];
529 Any const & rhs = m_data[ i_rhs ];
530 // <VOID/> is less than everything else
531 if ( !lhs.hasValue() )
532 return m_sortAscending;
533 if ( !rhs.hasValue() )
534 return !m_sortAscending;
536 // actually compare
537 if ( m_sortAscending )
538 return m_predicate.isLess( lhs, rhs );
539 else
540 return m_predicate.isLess( rhs, lhs );
543 private:
544 ::std::vector< Any > const & m_data;
545 ::comphelper::IKeyPredicateLess const & m_predicate;
546 bool const m_sortAscending;
551 bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending )
553 ::sal_Int32 const rowCount( getRowCount() );
554 ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
558 // build an unsorted translation table, and retrieve the unsorted data
559 ::std::vector< Any > aColumnData( rowCount );
560 Type dataType;
561 for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
563 aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
564 aPublicToPrivate[ rowIndex ] = rowIndex;
566 // determine the data types we assume for the complete column
567 if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
568 dataType = aColumnData[ rowIndex ].getValueType();
571 // get predicate object
572 ::std::unique_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
573 ENSURE_OR_RETURN_FALSE( pPredicate.get(), "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!" );
575 // then sort
576 CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
577 ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
579 catch( const Exception& )
581 DBG_UNHANDLED_EXCEPTION();
582 return false;
585 // also build the "private to public" mapping
586 ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
587 for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
588 aPrivateToPublic[ aPublicToPrivate[i] ] = i;
590 m_publicToPrivateRowIndex.swap( aPublicToPrivate );
591 m_privateToPublicRowIndex.swap( aPrivateToPublic );
593 return true;
597 void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, sal_Bool i_sortAscending )
599 MethodGuard aGuard( *this, rBHelper );
601 if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
602 throw IndexOutOfBoundsException( OUString(), *this );
604 if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
605 return;
607 m_currentSortColumn = i_columnIndex;
608 m_sortAscending = i_sortAscending;
610 impl_broadcast(
611 &XGridDataListener::dataChanged,
612 GridDataEvent( *this, -1, -1, -1, -1 ),
613 aGuard
618 void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
620 lcl_clear( m_publicToPrivateRowIndex );
621 lcl_clear( m_privateToPublicRowIndex );
623 m_currentSortColumn = -1;
624 m_sortAscending = true;
628 void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
630 impl_removeColumnSort_noBroadcast();
631 impl_broadcast(
632 &XGridDataListener::dataChanged,
633 GridDataEvent( *this, -1, -1, -1, -1 ),
634 i_instanceLock
639 void SAL_CALL SortableGridDataModel::removeColumnSort( )
641 MethodGuard aGuard( *this, rBHelper );
642 impl_removeColumnSort( aGuard );
646 css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( )
648 MethodGuard aGuard( *this, rBHelper );
650 return css::beans::Pair< ::sal_Int32, sal_Bool >( m_currentSortColumn, m_sortAscending );
654 void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
656 MethodGuard aGuard( *this, rBHelper );
658 Reference< XMutableGridDataModel > const delegator( m_delegator );
659 aGuard.clear();
660 delegator->addRow( i_heading, i_data );
664 void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
666 MethodGuard aGuard( *this, rBHelper );
668 Reference< XMutableGridDataModel > const delegator( m_delegator );
669 aGuard.clear();
670 delegator->addRows( i_headings, i_data );
674 void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
676 MethodGuard aGuard( *this, rBHelper );
678 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
679 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
681 Reference< XMutableGridDataModel > const delegator( m_delegator );
682 aGuard.clear();
683 delegator->insertRow( rowIndex, i_heading, i_data );
687 void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
689 MethodGuard aGuard( *this, rBHelper );
691 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
692 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
694 Reference< XMutableGridDataModel > const delegator( m_delegator );
695 aGuard.clear();
696 delegator->insertRows( rowIndex, i_headings, i_data );
700 void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
702 MethodGuard aGuard( *this, rBHelper );
704 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
706 Reference< XMutableGridDataModel > const delegator( m_delegator );
707 aGuard.clear();
708 delegator->removeRow( rowIndex );
712 void SAL_CALL SortableGridDataModel::removeAllRows( )
714 MethodGuard aGuard( *this, rBHelper );
716 Reference< XMutableGridDataModel > const delegator( m_delegator );
717 aGuard.clear();
718 delegator->removeAllRows();
722 void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
724 MethodGuard aGuard( *this, rBHelper );
726 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
728 Reference< XMutableGridDataModel > const delegator( m_delegator );
729 aGuard.clear();
730 delegator->updateCellData( i_columnIndex, rowIndex, i_value );
734 void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
736 MethodGuard aGuard( *this, rBHelper );
738 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
740 Reference< XMutableGridDataModel > const delegator( m_delegator );
741 aGuard.clear();
742 delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
746 void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
748 MethodGuard aGuard( *this, rBHelper );
750 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
752 Reference< XMutableGridDataModel > const delegator( m_delegator );
753 aGuard.clear();
754 delegator->updateRowHeading( rowIndex, i_heading );
758 void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
760 MethodGuard aGuard( *this, rBHelper );
762 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
764 Reference< XMutableGridDataModel > const delegator( m_delegator );
765 aGuard.clear();
766 delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
770 void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
772 MethodGuard aGuard( *this, rBHelper );
774 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
776 Reference< XMutableGridDataModel > const delegator( m_delegator );
777 aGuard.clear();
778 delegator->updateRowToolTip( rowIndex, i_value );
782 void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener )
784 rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
788 void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener )
790 rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
794 ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount()
796 MethodGuard aGuard( *this, rBHelper );
798 Reference< XMutableGridDataModel > const delegator( m_delegator );
799 aGuard.clear();
800 return delegator->getRowCount();
804 ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount()
806 MethodGuard aGuard( *this, rBHelper );
808 Reference< XMutableGridDataModel > const delegator( m_delegator );
809 aGuard.clear();
810 return delegator->getColumnCount();
814 Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
816 MethodGuard aGuard( *this, rBHelper );
818 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
820 Reference< XMutableGridDataModel > const delegator( m_delegator );
821 aGuard.clear();
822 return delegator->getCellData( i_columnIndex, rowIndex );
826 Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
828 MethodGuard aGuard( *this, rBHelper );
830 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
832 Reference< XMutableGridDataModel > const delegator( m_delegator );
833 aGuard.clear();
834 return delegator->getCellToolTip( i_columnIndex, rowIndex );
838 Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex )
840 MethodGuard aGuard( *this, rBHelper );
842 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
844 Reference< XMutableGridDataModel > const delegator( m_delegator );
845 aGuard.clear();
846 return delegator->getRowHeading( rowIndex );
850 Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
852 MethodGuard aGuard( *this, rBHelper );
854 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
856 Reference< XMutableGridDataModel > const delegator( m_delegator );
857 aGuard.clear();
858 return delegator->getRowData( rowIndex );
862 void SAL_CALL SortableGridDataModel::disposing()
864 m_currentSortColumn = -1;
866 Reference< XComponent > const delegatorComponent( m_delegator.get() );
867 m_delegator->removeGridDataListener( this );
868 m_delegator.clear();
869 delegatorComponent->dispose();
871 Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
872 m_collator.clear();
873 if ( collatorComponent.is() )
874 collatorComponent->dispose();
876 lcl_clear( m_publicToPrivateRowIndex );
877 lcl_clear( m_privateToPublicRowIndex );
881 Reference< css::util::XCloneable > SAL_CALL SortableGridDataModel::createClone( )
883 MethodGuard aGuard( *this, rBHelper );
885 return new SortableGridDataModel( *this );
889 OUString SAL_CALL SortableGridDataModel::getImplementationName( )
891 return OUString( "org.openoffice.comp.toolkit.SortableGridDataModel" );
894 sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName )
896 return cppu::supportsService(this, i_serviceName);
899 Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( )
901 Sequence< OUString > aServiceNames { "com.sun.star.awt.grid.SortableGridDataModel" };
902 return aServiceNames;
906 ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
908 if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
909 throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
911 if ( !impl_isSorted_nothrow() )
912 // no need to translate anything
913 return i_publicRowIndex;
915 ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
916 "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
917 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
918 // elements
920 return m_publicToPrivateRowIndex[ i_publicRowIndex ];
924 ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
926 if ( !impl_isSorted_nothrow() )
927 // no need to translate anything
928 return i_privateRowIndex;
930 if ( i_privateRowIndex < 0 )
931 return i_privateRowIndex;
933 ENSURE_OR_RETURN( size_t( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
934 "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
936 return m_privateToPublicRowIndex[ i_privateRowIndex ];
941 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
942 org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(
943 css::uno::XComponentContext *context,
944 css::uno::Sequence<css::uno::Any> const &)
946 return cppu::acquire(new SortableGridDataModel(context));
949 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */