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 <comphelper/compbase.hxx>
34 #include <comphelper/interfacecontainer4.hxx>
35 #include <cppuhelper/implbase1.hxx>
36 #include <comphelper/anycompare.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <comphelper/diagnose_ex.hxx>
39 #include <i18nlangtag/languagetag.hxx>
40 #include <o3tl/safeint.hxx>
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
;
55 typedef ::comphelper::WeakComponentImplHelper
< css::awt::grid::XSortableMutableGridDataModel
56 , css::awt::grid::XGridDataListener
57 , css::lang::XServiceInfo
58 , css::lang::XInitialization
59 > SortableGridDataModel_Base
;
60 class SortableGridDataModel
:public SortableGridDataModel_Base
63 explicit SortableGridDataModel( const css::uno::Reference
< css::uno::XComponentContext
> & rxContext
);
64 SortableGridDataModel( SortableGridDataModel
const & i_copySource
);
66 bool isInitialized() const { return m_isInitialized
; }
69 virtual ~SortableGridDataModel() override
;
73 virtual void SAL_CALL
sortByColumn( ::sal_Int32 ColumnIndex
, sal_Bool SortAscending
) override
;
74 virtual void SAL_CALL
removeColumnSort( ) override
;
75 virtual css::beans::Pair
< ::sal_Int32
, sal_Bool
> SAL_CALL
getCurrentSortOrder( ) override
;
77 // XMutableGridDataModel
78 virtual void SAL_CALL
addRow( const css::uno::Any
& Heading
, const css::uno::Sequence
< css::uno::Any
>& Data
) override
;
79 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
;
80 virtual void SAL_CALL
insertRow( ::sal_Int32 i_index
, const css::uno::Any
& i_heading
, const css::uno::Sequence
< css::uno::Any
>& Data
) override
;
81 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
;
82 virtual void SAL_CALL
removeRow( ::sal_Int32 RowIndex
) override
;
83 virtual void SAL_CALL
removeAllRows( ) override
;
84 virtual void SAL_CALL
updateCellData( ::sal_Int32 ColumnIndex
, ::sal_Int32 RowIndex
, const css::uno::Any
& Value
) override
;
85 virtual void SAL_CALL
updateRowData( const css::uno::Sequence
< ::sal_Int32
>& ColumnIndexes
, ::sal_Int32 RowIndex
, const css::uno::Sequence
< css::uno::Any
>& Values
) override
;
86 virtual void SAL_CALL
updateRowHeading( ::sal_Int32 RowIndex
, const css::uno::Any
& Heading
) override
;
87 virtual void SAL_CALL
updateCellToolTip( ::sal_Int32 ColumnIndex
, ::sal_Int32 RowIndex
, const css::uno::Any
& Value
) override
;
88 virtual void SAL_CALL
updateRowToolTip( ::sal_Int32 RowIndex
, const css::uno::Any
& Value
) override
;
89 virtual void SAL_CALL
addGridDataListener( const css::uno::Reference
< css::awt::grid::XGridDataListener
>& Listener
) override
;
90 virtual void SAL_CALL
removeGridDataListener( const css::uno::Reference
< css::awt::grid::XGridDataListener
>& Listener
) override
;
93 virtual ::sal_Int32 SAL_CALL
getRowCount() override
;
94 virtual ::sal_Int32 SAL_CALL
getColumnCount() override
;
95 virtual css::uno::Any SAL_CALL
getCellData( ::sal_Int32 Column
, ::sal_Int32 RowIndex
) override
;
96 virtual css::uno::Any SAL_CALL
getCellToolTip( ::sal_Int32 Column
, ::sal_Int32 RowIndex
) override
;
97 virtual css::uno::Any SAL_CALL
getRowHeading( ::sal_Int32 RowIndex
) override
;
98 virtual css::uno::Sequence
< css::uno::Any
> SAL_CALL
getRowData( ::sal_Int32 RowIndex
) override
;
101 virtual void disposing(std::unique_lock
<std::mutex
>& rGuard
) override
;
104 virtual css::uno::Reference
< css::util::XCloneable
> SAL_CALL
createClone( ) override
;
107 virtual OUString SAL_CALL
getImplementationName( ) override
;
108 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
109 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
112 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) override
;
115 virtual void SAL_CALL
rowsInserted( const css::awt::grid::GridDataEvent
& Event
) override
;
116 virtual void SAL_CALL
rowsRemoved( const css::awt::grid::GridDataEvent
& Event
) override
;
117 virtual void SAL_CALL
dataChanged( const css::awt::grid::GridDataEvent
& Event
) override
;
118 virtual void SAL_CALL
rowHeadingChanged( const css::awt::grid::GridDataEvent
& Event
) override
;
121 virtual void SAL_CALL
disposing( const css::lang::EventObject
& i_event
) override
;
124 /** translates the given public index into one to be passed to our delegator
125 @throws css::lang::IndexOutOfBoundsException
126 if the given index does not denote a valid row
128 ::sal_Int32
impl_getPrivateRowIndex_throw( std::unique_lock
<std::mutex
>& rGuard
, ::sal_Int32
const i_publicRowIndex
) const;
130 /** translates the given private row index to a public one
132 ::sal_Int32
impl_getPublicRowIndex_nothrow( ::sal_Int32
const i_privateRowIndex
) const;
134 bool impl_isSorted_nothrow() const
136 return m_currentSortColumn
>= 0;
139 /** rebuilds the index translation structure.
141 Neither <member>m_currentSortColumn</member> nor <member>m_sortAscending</member> are touched by this method.
142 Also, the given column index is not checked, this is the responsibility of the caller.
144 bool impl_reIndex_nothrow( std::unique_lock
<std::mutex
>& rGuard
, ::sal_Int32
const i_columnIndex
, bool const i_sortAscending
);
146 /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
149 css::awt::grid::GridDataEvent
150 impl_createPublicEvent( css::awt::grid::GridDataEvent
const & i_originalEvent
) const;
152 /** broadcasts the given event to our registered XGridDataListeners
155 void ( SAL_CALL
css::awt::grid::XGridDataListener::*i_listenerMethod
)( const css::awt::grid::GridDataEvent
& ),
156 css::awt::grid::GridDataEvent
const & i_publicEvent
,
157 std::unique_lock
<std::mutex
>& i_instanceLock
160 /** rebuilds our indexes, notifying row removal and row addition events
162 First, a rowsRemoved event is notified to our registered listeners. Then, the index translation tables are
163 rebuilt, and a rowsInserted event is notified.
165 Only to be called when we're sorted.
167 void impl_rebuildIndexesAndNotify( std::unique_lock
<std::mutex
>& i_instanceLock
);
169 /** removes the current sorting, and notifies a change of all data
171 void impl_removeColumnSort( std::unique_lock
<std::mutex
>& i_instanceLock
);
173 /** removes the current sorting, without any broadcast
175 void impl_removeColumnSort_noBroadcast();
177 void throwIfNotInitialized()
179 if (!isInitialized())
180 throw css::lang::NotInitializedException( OUString(), *this );
184 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
185 bool m_isInitialized
;
186 css::uno::Reference
< css::awt::grid::XMutableGridDataModel
> m_delegator
;
187 css::uno::Reference
< css::i18n::XCollator
> m_collator
;
188 ::sal_Int32 m_currentSortColumn
;
189 bool m_sortAscending
;
190 ::std::vector
< ::sal_Int32
> m_publicToPrivateRowIndex
;
191 ::std::vector
< ::sal_Int32
> m_privateToPublicRowIndex
;
192 comphelper::OInterfaceContainerHelper4
<XGridDataListener
> m_GridListeners
;
195 template< class STLCONTAINER
>
196 void lcl_clear( STLCONTAINER
& i_container
)
198 STLCONTAINER().swap(i_container
);
201 SortableGridDataModel::SortableGridDataModel( Reference
< XComponentContext
> const & rxContext
)
202 :m_xContext( rxContext
)
203 ,m_isInitialized( false )
206 ,m_currentSortColumn( -1 )
207 ,m_sortAscending( true )
208 ,m_publicToPrivateRowIndex()
209 ,m_privateToPublicRowIndex()
213 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel
const & i_copySource
)
214 :m_xContext( i_copySource
.m_xContext
)
215 ,m_isInitialized( true )
217 ,m_collator( i_copySource
.m_collator
)
218 ,m_currentSortColumn( i_copySource
.m_currentSortColumn
)
219 ,m_sortAscending( i_copySource
.m_sortAscending
)
220 ,m_publicToPrivateRowIndex( i_copySource
.m_publicToPrivateRowIndex
)
221 ,m_privateToPublicRowIndex( i_copySource
.m_privateToPublicRowIndex
)
223 ENSURE_OR_THROW( i_copySource
.m_delegator
.is(),
224 "not expected to be called for a disposed copy source!" );
225 m_delegator
.set( i_copySource
.m_delegator
->createClone(), UNO_QUERY_THROW
);
229 SortableGridDataModel::~SortableGridDataModel()
235 Reference
< XCollator
> lcl_loadDefaultCollator_throw( const Reference
<XComponentContext
> & rxContext
)
237 Reference
< XCollator
> const xCollator
= Collator::create( rxContext
);
238 xCollator
->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
242 void SAL_CALL
SortableGridDataModel::initialize( const Sequence
< Any
>& i_arguments
)
244 std::unique_lock
aGuard( m_aMutex
);
245 throwIfDisposed(aGuard
);
247 if ( m_delegator
.is() )
248 throw AlreadyInitializedException( OUString(), *this );
250 Reference
< XMutableGridDataModel
> xDelegator
;
251 Reference
< XCollator
> xCollator
;
252 switch ( i_arguments
.getLength() )
254 case 1: // SortableGridDataModel.create( XMutableGridDataModel )
255 xDelegator
.set( i_arguments
[0], UNO_QUERY
);
256 xCollator
= lcl_loadDefaultCollator_throw( m_xContext
);
259 case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
260 xDelegator
.set( i_arguments
[0], UNO_QUERY
);
261 xCollator
.set( i_arguments
[1], UNO_QUERY
);
262 if ( !xCollator
.is() )
263 throw IllegalArgumentException( OUString(), *this, 2 );
266 if ( !xDelegator
.is() )
267 throw IllegalArgumentException( OUString(), *this, 1 );
269 m_delegator
= std::move(xDelegator
);
270 m_collator
= std::move(xCollator
);
272 m_delegator
->addGridDataListener( this );
274 m_isInitialized
= true;
278 GridDataEvent
SortableGridDataModel::impl_createPublicEvent( GridDataEvent
const & i_originalEvent
) const
280 GridDataEvent
aEvent( i_originalEvent
);
281 aEvent
.Source
= *const_cast< SortableGridDataModel
* >( this );
282 aEvent
.FirstRow
= impl_getPublicRowIndex_nothrow( aEvent
.FirstRow
);
283 aEvent
.LastRow
= impl_getPublicRowIndex_nothrow( aEvent
.LastRow
);
288 void SortableGridDataModel::impl_broadcast( void ( SAL_CALL
XGridDataListener::*i_listenerMethod
)( const GridDataEvent
& ),
289 GridDataEvent
const & i_publicEvent
, std::unique_lock
<std::mutex
>& i_instanceLock
)
291 m_GridListeners
.notifyEach( i_instanceLock
, i_listenerMethod
, i_publicEvent
);
295 void SAL_CALL
SortableGridDataModel::rowsInserted( const GridDataEvent
& i_event
)
297 std::unique_lock
aGuard(m_aMutex
);
298 throwIfNotInitialized();
300 if ( impl_isSorted_nothrow() )
302 // no infrastructure is in place currently to sort the new row to its proper location,
303 // so we remove the sorting here.
304 impl_removeColumnSort( aGuard
);
307 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
308 impl_broadcast( &XGridDataListener::rowsInserted
, aEvent
, aGuard
);
311 void lcl_decrementValuesGreaterThan( ::std::vector
< ::sal_Int32
> & io_indexMap
, sal_Int32
const i_threshold
)
313 for ( auto& rIndex
: io_indexMap
)
315 if ( rIndex
>= i_threshold
)
320 void SortableGridDataModel::impl_rebuildIndexesAndNotify( std::unique_lock
<std::mutex
>& i_instanceLock
)
322 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
325 lcl_clear( m_publicToPrivateRowIndex
);
326 lcl_clear( m_privateToPublicRowIndex
);
329 if ( !impl_reIndex_nothrow( i_instanceLock
, m_currentSortColumn
, m_sortAscending
) )
331 impl_removeColumnSort( i_instanceLock
);
335 // broadcast an artificial event, saying that all rows have been removed
336 GridDataEvent
const aRemovalEvent( *this, -1, -1, -1, -1 );
337 impl_broadcast( &XGridDataListener::rowsRemoved
, aRemovalEvent
, i_instanceLock
);
339 // broadcast an artificial event, saying that n rows have been added
340 GridDataEvent
const aAdditionEvent( *this, -1, -1, 0, m_delegator
->getRowCount() - 1 );
341 impl_broadcast( &XGridDataListener::rowsInserted
, aAdditionEvent
, i_instanceLock
);
345 void SAL_CALL
SortableGridDataModel::rowsRemoved( const GridDataEvent
& i_event
)
347 std::unique_lock
aGuard(m_aMutex
);
348 throwIfNotInitialized();
350 // if the data is not sorted, broadcast the event unchanged
351 if ( !impl_isSorted_nothrow() )
353 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
354 impl_broadcast( &XGridDataListener::rowsRemoved
, aEvent
, aGuard
);
358 // if all rows have been removed, also simply multiplex to own listeners
359 if ( i_event
.FirstRow
< 0 )
361 lcl_clear( m_publicToPrivateRowIndex
);
362 lcl_clear( m_privateToPublicRowIndex
);
363 GridDataEvent
aEvent( i_event
);
364 aEvent
.Source
= *this;
365 impl_broadcast( &XGridDataListener::rowsRemoved
, aEvent
, aGuard
);
369 bool needReIndex
= false;
370 if ( i_event
.FirstRow
!= i_event
.LastRow
)
372 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
375 else if ( o3tl::make_unsigned( i_event
.FirstRow
) >= m_privateToPublicRowIndex
.size() )
377 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
383 impl_rebuildIndexesAndNotify( aGuard
);
387 // build public event version
388 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
390 // remove the entries from the index maps
391 sal_Int32
const privateIndex
= i_event
.FirstRow
;
392 sal_Int32
const publicIndex
= aEvent
.FirstRow
;
394 m_publicToPrivateRowIndex
.erase( m_publicToPrivateRowIndex
.begin() + publicIndex
);
395 m_privateToPublicRowIndex
.erase( m_privateToPublicRowIndex
.begin() + privateIndex
);
397 // adjust remaining entries in the index maps
398 lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex
, privateIndex
);
399 lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex
, publicIndex
);
401 // broadcast the event
402 impl_broadcast( &XGridDataListener::rowsRemoved
, aEvent
, aGuard
);
406 void SAL_CALL
SortableGridDataModel::dataChanged( const GridDataEvent
& i_event
)
408 std::unique_lock
aGuard(m_aMutex
);
409 throwIfNotInitialized();
411 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
412 impl_broadcast( &XGridDataListener::dataChanged
, aEvent
, aGuard
);
416 void SAL_CALL
SortableGridDataModel::rowHeadingChanged( const GridDataEvent
& i_event
)
418 std::unique_lock
aGuard(m_aMutex
);
419 throwIfNotInitialized();
421 GridDataEvent
const aEvent( impl_createPublicEvent( i_event
) );
422 impl_broadcast( &XGridDataListener::rowHeadingChanged
, aEvent
, aGuard
);
426 void SAL_CALL
SortableGridDataModel::disposing( const EventObject
& )
430 class CellDataLessComparison
433 CellDataLessComparison(
434 ::std::vector
< Any
> const & i_data
,
435 ::comphelper::IKeyPredicateLess
const & i_predicate
,
436 bool const i_sortAscending
439 ,m_predicate( i_predicate
)
440 ,m_sortAscending( i_sortAscending
)
444 bool operator()( sal_Int32
const i_lhs
, sal_Int32
const i_rhs
) const
446 Any
const & lhs
= m_data
[ i_lhs
];
447 Any
const & rhs
= m_data
[ i_rhs
];
448 // <VOID/> is less than everything else
449 if ( !lhs
.hasValue() )
450 return m_sortAscending
;
451 if ( !rhs
.hasValue() )
452 return !m_sortAscending
;
455 if ( m_sortAscending
)
456 return m_predicate
.isLess( lhs
, rhs
);
458 return m_predicate
.isLess( rhs
, lhs
);
462 ::std::vector
< Any
> const & m_data
;
463 ::comphelper::IKeyPredicateLess
const & m_predicate
;
464 bool const m_sortAscending
;
467 bool SortableGridDataModel::impl_reIndex_nothrow( std::unique_lock
<std::mutex
>& rGuard
, ::sal_Int32
const i_columnIndex
, bool const i_sortAscending
)
469 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
471 ::sal_Int32
const rowCount
= delegator
->getRowCount();
473 ::std::vector
< ::sal_Int32
> aPublicToPrivate( rowCount
);
477 // build an unsorted translation table, and retrieve the unsorted data
478 ::std::vector
< Any
> aColumnData( rowCount
);
480 for ( ::sal_Int32 rowIndex
= 0; rowIndex
< rowCount
; ++rowIndex
)
482 aColumnData
[ rowIndex
] = m_delegator
->getCellData( i_columnIndex
, rowIndex
);
483 aPublicToPrivate
[ rowIndex
] = rowIndex
;
485 // determine the data types we assume for the complete column
486 if ( ( dataType
.getTypeClass() == TypeClass_VOID
) && aColumnData
[ rowIndex
].hasValue() )
487 dataType
= aColumnData
[ rowIndex
].getValueType();
490 // get predicate object
491 ::std::unique_ptr
< ::comphelper::IKeyPredicateLess
> const pPredicate( ::comphelper::getStandardLessPredicate( dataType
, m_collator
) );
492 ENSURE_OR_RETURN_FALSE(
493 pPredicate
, "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!");
496 CellDataLessComparison
const aComparator( aColumnData
, *pPredicate
, i_sortAscending
);
497 ::std::sort( aPublicToPrivate
.begin(), aPublicToPrivate
.end(), aComparator
);
499 catch( const Exception
& )
501 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
505 // also build the "private to public" mapping
506 ::std::vector
< sal_Int32
> aPrivateToPublic( aPublicToPrivate
.size() );
507 for ( size_t i
=0; i
<aPublicToPrivate
.size(); ++i
)
508 aPrivateToPublic
[ aPublicToPrivate
[i
] ] = i
;
510 m_publicToPrivateRowIndex
.swap( aPublicToPrivate
);
511 m_privateToPublicRowIndex
.swap( aPrivateToPublic
);
517 void SAL_CALL
SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex
, sal_Bool i_sortAscending
)
519 std::unique_lock
aGuard(m_aMutex
);
520 throwIfNotInitialized();
522 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
524 sal_Int32 nColumnCount
= delegator
->getColumnCount();
526 if ( ( i_columnIndex
< 0 ) || ( i_columnIndex
>= nColumnCount
) )
527 throw IndexOutOfBoundsException( OUString(), *this );
529 if ( !impl_reIndex_nothrow( aGuard
, i_columnIndex
, i_sortAscending
) )
532 m_currentSortColumn
= i_columnIndex
;
533 m_sortAscending
= i_sortAscending
;
536 &XGridDataListener::dataChanged
,
537 GridDataEvent( *this, -1, -1, -1, -1 ),
543 void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
545 lcl_clear( m_publicToPrivateRowIndex
);
546 lcl_clear( m_privateToPublicRowIndex
);
548 m_currentSortColumn
= -1;
549 m_sortAscending
= true;
553 void SortableGridDataModel::impl_removeColumnSort( std::unique_lock
<std::mutex
>& i_instanceLock
)
555 impl_removeColumnSort_noBroadcast();
557 &XGridDataListener::dataChanged
,
558 GridDataEvent( *this, -1, -1, -1, -1 ),
564 void SAL_CALL
SortableGridDataModel::removeColumnSort( )
566 std::unique_lock
aGuard(m_aMutex
);
567 throwIfNotInitialized();
568 impl_removeColumnSort( aGuard
);
572 css::beans::Pair
< ::sal_Int32
, sal_Bool
> SAL_CALL
SortableGridDataModel::getCurrentSortOrder( )
574 std::unique_lock
aGuard(m_aMutex
);
575 throwIfNotInitialized();
577 return css::beans::Pair
< ::sal_Int32
, sal_Bool
>( m_currentSortColumn
, m_sortAscending
);
581 void SAL_CALL
SortableGridDataModel::addRow( const Any
& i_heading
, const Sequence
< Any
>& i_data
)
583 std::unique_lock
aGuard(m_aMutex
);
584 throwIfNotInitialized();
586 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
588 delegator
->addRow( i_heading
, i_data
);
592 void SAL_CALL
SortableGridDataModel::addRows( const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
)
594 std::unique_lock
aGuard(m_aMutex
);
595 throwIfNotInitialized();
597 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
599 delegator
->addRows( i_headings
, i_data
);
603 void SAL_CALL
SortableGridDataModel::insertRow( ::sal_Int32 i_index
, const Any
& i_heading
, const Sequence
< Any
>& i_data
)
605 std::unique_lock
aGuard(m_aMutex
);
606 throwIfNotInitialized();
608 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
610 sal_Int32 nRowCount
= delegator
->getRowCount();
613 ::sal_Int32
const rowIndex
= i_index
== nRowCount
? i_index
: impl_getPrivateRowIndex_throw( aGuard
, i_index
);
614 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
617 delegator
->insertRow( rowIndex
, i_heading
, i_data
);
621 void SAL_CALL
SortableGridDataModel::insertRows( ::sal_Int32 i_index
, const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
)
623 std::unique_lock
aGuard(m_aMutex
);
624 throwIfNotInitialized();
626 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
628 sal_Int32 nRowCount
= delegator
->getRowCount();
631 ::sal_Int32
const rowIndex
= i_index
== nRowCount
? i_index
: impl_getPrivateRowIndex_throw( aGuard
, i_index
);
632 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
635 delegator
->insertRows( rowIndex
, i_headings
, i_data
);
639 void SAL_CALL
SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex
)
641 std::unique_lock
aGuard(m_aMutex
);
642 throwIfNotInitialized();
644 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
646 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
648 delegator
->removeRow( rowIndex
);
652 void SAL_CALL
SortableGridDataModel::removeAllRows( )
654 std::unique_lock
aGuard(m_aMutex
);
655 throwIfNotInitialized();
657 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
659 delegator
->removeAllRows();
663 void SAL_CALL
SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
)
665 std::unique_lock
aGuard(m_aMutex
);
666 throwIfNotInitialized();
668 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
670 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
672 delegator
->updateCellData( i_columnIndex
, rowIndex
, i_value
);
676 void SAL_CALL
SortableGridDataModel::updateRowData( const Sequence
< ::sal_Int32
>& i_columnIndexes
, ::sal_Int32 i_rowIndex
, const Sequence
< Any
>& i_values
)
678 std::unique_lock
aGuard(m_aMutex
);
679 throwIfNotInitialized();
681 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
683 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
685 delegator
->updateRowData( i_columnIndexes
, rowIndex
, i_values
);
689 void SAL_CALL
SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex
, const Any
& i_heading
)
691 std::unique_lock
aGuard(m_aMutex
);
692 throwIfNotInitialized();
694 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
696 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
698 delegator
->updateRowHeading( rowIndex
, i_heading
);
702 void SAL_CALL
SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
)
704 std::unique_lock
aGuard(m_aMutex
);
705 throwIfNotInitialized();
707 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
709 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
711 delegator
->updateCellToolTip( i_columnIndex
, rowIndex
, i_value
);
715 void SAL_CALL
SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex
, const Any
& i_value
)
717 std::unique_lock
aGuard(m_aMutex
);
718 throwIfNotInitialized();
720 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
722 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
724 delegator
->updateRowToolTip( rowIndex
, i_value
);
728 void SAL_CALL
SortableGridDataModel::addGridDataListener( const Reference
< XGridDataListener
>& i_listener
)
730 std::unique_lock
aGuard(m_aMutex
);
731 m_GridListeners
.addInterface( aGuard
, i_listener
);
735 void SAL_CALL
SortableGridDataModel::removeGridDataListener( const Reference
< XGridDataListener
>& i_listener
)
737 std::unique_lock
aGuard(m_aMutex
);
738 m_GridListeners
.removeInterface( aGuard
, i_listener
);
742 ::sal_Int32 SAL_CALL
SortableGridDataModel::getRowCount()
744 std::unique_lock
aGuard(m_aMutex
);
745 throwIfNotInitialized();
747 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
749 return delegator
->getRowCount();
753 ::sal_Int32 SAL_CALL
SortableGridDataModel::getColumnCount()
755 std::unique_lock
aGuard(m_aMutex
);
756 throwIfNotInitialized();
758 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
760 return delegator
->getColumnCount();
764 Any SAL_CALL
SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
)
766 std::unique_lock
aGuard(m_aMutex
);
767 throwIfNotInitialized();
769 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
771 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
773 return delegator
->getCellData( i_columnIndex
, rowIndex
);
777 Any SAL_CALL
SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
)
779 std::unique_lock
aGuard(m_aMutex
);
780 throwIfNotInitialized();
782 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
784 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
786 return delegator
->getCellToolTip( i_columnIndex
, rowIndex
);
790 Any SAL_CALL
SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex
)
792 std::unique_lock
aGuard(m_aMutex
);
793 throwIfNotInitialized();
795 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
797 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
799 return delegator
->getRowHeading( rowIndex
);
803 Sequence
< Any
> SAL_CALL
SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex
)
805 std::unique_lock
aGuard(m_aMutex
);
806 throwIfNotInitialized();
808 ::sal_Int32
const rowIndex
= impl_getPrivateRowIndex_throw( aGuard
, i_rowIndex
);
810 Reference
< XMutableGridDataModel
> const delegator( m_delegator
);
812 return delegator
->getRowData( rowIndex
);
816 void SortableGridDataModel::disposing(std::unique_lock
<std::mutex
>& /*rGuard*/)
818 m_currentSortColumn
= -1;
820 Reference
< XComponent
> const delegatorComponent( m_delegator
);
821 m_delegator
->removeGridDataListener( this );
823 delegatorComponent
->dispose();
825 Reference
< XComponent
> const collatorComponent( m_collator
, UNO_QUERY
);
827 if ( collatorComponent
.is() )
828 collatorComponent
->dispose();
830 lcl_clear( m_publicToPrivateRowIndex
);
831 lcl_clear( m_privateToPublicRowIndex
);
835 Reference
< css::util::XCloneable
> SAL_CALL
SortableGridDataModel::createClone( )
837 std::unique_lock
aGuard(m_aMutex
);
838 throwIfNotInitialized();
840 return new SortableGridDataModel( *this );
844 OUString SAL_CALL
SortableGridDataModel::getImplementationName( )
846 return u
"org.openoffice.comp.toolkit.SortableGridDataModel"_ustr
;
849 sal_Bool SAL_CALL
SortableGridDataModel::supportsService( const OUString
& i_serviceName
)
851 return cppu::supportsService(this, i_serviceName
);
854 Sequence
< OUString
> SAL_CALL
SortableGridDataModel::getSupportedServiceNames( )
856 return { u
"com.sun.star.awt.grid.SortableGridDataModel"_ustr
};
860 ::sal_Int32
SortableGridDataModel::impl_getPrivateRowIndex_throw( std::unique_lock
<std::mutex
>& rGuard
, ::sal_Int32
const i_publicRowIndex
) const
863 sal_Int32 nRowCount
= m_delegator
->getRowCount();
865 if ( ( i_publicRowIndex
< 0 ) || ( i_publicRowIndex
>= nRowCount
) )
866 throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel
* >( this ) );
868 if ( !impl_isSorted_nothrow() )
869 // no need to translate anything
870 return i_publicRowIndex
;
872 ENSURE_OR_RETURN( o3tl::make_unsigned( i_publicRowIndex
) < m_publicToPrivateRowIndex
.size(),
873 "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex
);
874 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
877 return m_publicToPrivateRowIndex
[ i_publicRowIndex
];
881 ::sal_Int32
SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32
const i_privateRowIndex
) const
883 if ( !impl_isSorted_nothrow() )
884 // no need to translate anything
885 return i_privateRowIndex
;
887 if ( i_privateRowIndex
< 0 )
888 return i_privateRowIndex
;
890 ENSURE_OR_RETURN( o3tl::make_unsigned( i_privateRowIndex
) < m_privateToPublicRowIndex
.size(),
891 "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex
);
893 return m_privateToPublicRowIndex
[ i_privateRowIndex
];
898 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
899 org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(
900 css::uno::XComponentContext
*context
,
901 css::uno::Sequence
<css::uno::Any
> const &)
903 return cppu::acquire(new SortableGridDataModel(context
));
906 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */