1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <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
;
53 class SortableGridDataModel
;
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
67 explicit SortableGridDataModel( const css::uno::Reference
< css::uno::XComponentContext
> & rxContext
);
68 SortableGridDataModel( SortableGridDataModel
const & i_copySource
);
70 bool isInitialized() const { return m_isInitialized
; }
73 virtual ~SortableGridDataModel() override
;
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
;
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
;
105 virtual void SAL_CALL
disposing() override
;
108 virtual css::uno::Reference
< css::util::XCloneable
> SAL_CALL
createClone( ) override
;
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
;
116 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
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
;
125 virtual void SAL_CALL
disposing( const css::lang::EventObject
& i_event
) override
;
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
;
133 virtual css::uno::Sequence
< css::uno::Type
> SAL_CALL
getTypes( ) override
;
134 virtual css::uno::Sequence
< ::sal_Int8
> SAL_CALL
getImplementationId( ) override
;
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
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
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();
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
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
);
214 template< class STLCONTAINER
>
215 void lcl_clear( STLCONTAINER
& i_container
)
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 )
229 ,m_currentSortColumn( -1 )
230 ,m_sortAscending( true )
231 ,m_publicToPrivateRowIndex()
232 ,m_privateToPublicRowIndex()
237 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel
const & i_copySource
)
239 ,SortableGridDataModel_Base( m_aMutex
)
240 ,SortableGridDataModel_PrivateBase()
241 ,m_xContext( i_copySource
.m_xContext
)
242 ,m_isInitialized( true )
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
)
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
);
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
>();
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 );
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
);
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 );
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
);
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 )
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
);
380 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
381 impl_broadcast( &XGridDataListener::rowsInserted
, aEvent
, aGuard
);
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();
394 if ( *loop
>= i_threshold
)
401 void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard
& i_instanceLock
)
403 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
406 lcl_clear( m_publicToPrivateRowIndex
);
407 lcl_clear( m_privateToPublicRowIndex
);
410 if ( !impl_reIndex_nothrow( m_currentSortColumn
, m_sortAscending
) )
412 impl_removeColumnSort( i_instanceLock
);
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
);
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
);
450 bool needReIndex
= false;
451 if ( i_event
.FirstRow
!= i_event
.LastRow
)
453 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
456 else if ( size_t( i_event
.FirstRow
) >= m_privateToPublicRowIndex
.size() )
458 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
464 impl_rebuildIndexesAndNotify( aGuard
);
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
& )
512 class CellDataLessComparison
: public ::std::binary_function
< sal_Int32
, sal_Int32
, bool >
515 CellDataLessComparison(
516 ::std::vector
< Any
> const & i_data
,
517 ::comphelper::IKeyPredicateLess
& i_predicate
,
518 bool const i_sortAscending
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
;
537 if ( m_sortAscending
)
538 return m_predicate
.isLess( lhs
, rhs
);
540 return m_predicate
.isLess( rhs
, lhs
);
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
);
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!" );
576 CellDataLessComparison
const aComparator( aColumnData
, *pPredicate
, i_sortAscending
);
577 ::std::sort( aPublicToPrivate
.begin(), aPublicToPrivate
.end(), aComparator
);
579 catch( const Exception
& )
581 DBG_UNHANDLED_EXCEPTION();
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
);
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
) )
607 m_currentSortColumn
= i_columnIndex
;
608 m_sortAscending
= i_sortAscending
;
611 &XGridDataListener::dataChanged
,
612 GridDataEvent( *this, -1, -1, -1, -1 ),
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();
632 &XGridDataListener::dataChanged
,
633 GridDataEvent( *this, -1, -1, -1, -1 ),
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
);
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
);
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
);
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
);
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
);
708 delegator
->removeRow( rowIndex
);
712 void SAL_CALL
SortableGridDataModel::removeAllRows( )
714 MethodGuard
aGuard( *this, rBHelper
);
716 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
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
);
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
);
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
);
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
);
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
);
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
);
800 return delegator
->getRowCount();
804 ::sal_Int32 SAL_CALL
SortableGridDataModel::getColumnCount()
806 MethodGuard
aGuard( *this, rBHelper
);
808 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
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
);
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
);
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
);
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
);
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 );
869 delegatorComponent
->dispose();
871 Reference
< XComponent
> const collatorComponent( m_collator
, UNO_QUERY
);
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()|
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: */