LibreOffice Module toolkit (master) 1
sortablegriddatamodel.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
32
41#include <o3tl/safeint.hxx>
42#include <vcl/svapp.hxx>
43#include <vcl/settings.hxx>
44
45using namespace css::awt;
46using namespace css::awt::grid;
47using namespace css::i18n;
48using namespace css::lang;
49using namespace css::ucb;
50using namespace css::uno;
51
52namespace {
53
54class SortableGridDataModel;
55class MethodGuard;
56
57typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XSortableMutableGridDataModel
58 , css::lang::XServiceInfo
59 , css::lang::XInitialization
60 > SortableGridDataModel_Base;
61typedef ::cppu::ImplHelper1 < css::awt::grid::XGridDataListener
62 > SortableGridDataModel_PrivateBase;
63class SortableGridDataModel :public ::cppu::BaseMutex
64 ,public SortableGridDataModel_Base
65 ,public SortableGridDataModel_PrivateBase
66{
67public:
68 explicit SortableGridDataModel( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
69 SortableGridDataModel( SortableGridDataModel const & i_copySource );
70
71 bool isInitialized() const { return m_isInitialized; }
72
73protected:
74 virtual ~SortableGridDataModel() override;
75
76public:
77 // XSortableGridData
78 virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, sal_Bool SortAscending ) override;
79 virtual void SAL_CALL removeColumnSort( ) override;
80 virtual css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL getCurrentSortOrder( ) override;
81
82 // XMutableGridDataModel
83 virtual void SAL_CALL addRow( const css::uno::Any& Heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
84 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;
85 virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
86 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;
87 virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
88 virtual void SAL_CALL removeAllRows( ) override;
89 virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
90 virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
91 virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
92 virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
93 virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
94 virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
95 virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
96
97 // XGridDataModel
98 virtual ::sal_Int32 SAL_CALL getRowCount() override;
99 virtual ::sal_Int32 SAL_CALL getColumnCount() override;
100 virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
101 virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
102 virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
103 virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
104
105 // OComponentHelper
106 virtual void SAL_CALL disposing() override;
107
108 // XCloneable
109 virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
110
111 // XServiceInfo
112 virtual OUString SAL_CALL getImplementationName( ) override;
113 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
114 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
115
116 // XInitialization
117 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
118
119 // XGridDataListener
120 virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
121 virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
122 virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
123 virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
124
125 // XEventListener
126 virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
127
128 // XInterface
129 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
130 virtual void SAL_CALL acquire( ) noexcept final override;
131 virtual void SAL_CALL release( ) noexcept override;
132
133 // XTypeProvider
134 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
135 virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getImplementationId( ) override;
136
137private:
142 ::sal_Int32 impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const;
143
146 ::sal_Int32 impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const;
147
148 bool impl_isSorted_nothrow() const
149 {
150 return m_currentSortColumn >= 0;
151 }
152
158 bool impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending );
159
163 css::awt::grid::GridDataEvent
164 impl_createPublicEvent( css::awt::grid::GridDataEvent const & i_originalEvent ) const;
165
168 void impl_broadcast(
169 void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( const css::awt::grid::GridDataEvent & ),
170 css::awt::grid::GridDataEvent const & i_publicEvent,
171 MethodGuard& i_instanceLock
172 );
173
181 void impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock );
182
185 void impl_removeColumnSort( MethodGuard& i_instanceLock );
186
189 void impl_removeColumnSort_noBroadcast();
190
191private:
192 css::uno::Reference< css::uno::XComponentContext > m_xContext;
193 bool m_isInitialized;
194 css::uno::Reference< css::awt::grid::XMutableGridDataModel > m_delegator;
195 css::uno::Reference< css::i18n::XCollator > m_collator;
196 ::sal_Int32 m_currentSortColumn;
197 bool m_sortAscending;
198 ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
199 ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
200};
201
202class MethodGuard : public ::comphelper::ComponentGuard
203{
204public:
205 MethodGuard( SortableGridDataModel& i_component, ::cppu::OBroadcastHelper & i_broadcastHelper )
206 :comphelper::ComponentGuard( i_component, i_broadcastHelper )
207 {
208 if ( !i_component.isInitialized() )
209 throw css::lang::NotInitializedException( OUString(), i_component );
210 }
211};
212
213template< class STLCONTAINER >
214void lcl_clear( STLCONTAINER& i_container )
215{
216 STLCONTAINER().swap(i_container);
217}
218
219 SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
220 :SortableGridDataModel_Base( m_aMutex )
221 ,SortableGridDataModel_PrivateBase()
222 ,m_xContext( rxContext )
223 ,m_isInitialized( false )
224 ,m_delegator()
225 ,m_collator()
226 ,m_currentSortColumn( -1 )
227 ,m_sortAscending( true )
228 ,m_publicToPrivateRowIndex()
229 ,m_privateToPublicRowIndex()
230 {
231 }
232
233
234 SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
235 :cppu::BaseMutex()
236 ,SortableGridDataModel_Base( m_aMutex )
237 ,SortableGridDataModel_PrivateBase()
238 ,m_xContext( i_copySource.m_xContext )
239 ,m_isInitialized( true )
240 ,m_delegator()
241 ,m_collator( i_copySource.m_collator )
242 ,m_currentSortColumn( i_copySource.m_currentSortColumn )
243 ,m_sortAscending( i_copySource.m_sortAscending )
244 ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
245 ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
246 {
247 ENSURE_OR_THROW( i_copySource.m_delegator.is(),
248 "not expected to be called for a disposed copy source!" );
249 m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
250 }
251
252
253 SortableGridDataModel::~SortableGridDataModel()
254 {
255 if ( !rBHelper.bDisposed )
256 {
257 acquire();
258 dispose();
259 }
260 }
261
262
263 Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType )
264 {
265 Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
266 if ( !aReturn.hasValue() )
267 aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
268 return aReturn;
269 }
270
271
272 void SAL_CALL SortableGridDataModel::acquire( ) noexcept
273 {
274 SortableGridDataModel_Base::acquire();
275 }
276
277
278 void SAL_CALL SortableGridDataModel::release( ) noexcept
279 {
280 SortableGridDataModel_Base::release();
281 }
282
283
284 Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( )
285 {
286 return SortableGridDataModel_Base::getTypes();
287 // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
288 }
289
290
291 Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( )
292 {
293 return css::uno::Sequence<sal_Int8>();
294 }
295
296 Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
297 {
298 Reference< XCollator > const xCollator = Collator::create( rxContext );
299 xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
300 return xCollator;
301 }
302
303 void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments )
304 {
305 ::comphelper::ComponentGuard aGuard( *this, rBHelper );
306
307 if ( m_delegator.is() )
308 throw AlreadyInitializedException( OUString(), *this );
309
310 Reference< XMutableGridDataModel > xDelegator;
311 Reference< XCollator > xCollator;
312 switch ( i_arguments.getLength() )
313 {
314 case 1: // SortableGridDataModel.create( XMutableGridDataModel )
315 xDelegator.set( i_arguments[0], UNO_QUERY );
316 xCollator = lcl_loadDefaultCollator_throw( m_xContext );
317 break;
318
319 case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
320 xDelegator.set( i_arguments[0], UNO_QUERY );
321 xCollator.set( i_arguments[1], UNO_QUERY );
322 if ( !xCollator.is() )
323 throw IllegalArgumentException( OUString(), *this, 2 );
324 break;
325 }
326 if ( !xDelegator.is() )
327 throw IllegalArgumentException( OUString(), *this, 1 );
328
329 m_delegator = xDelegator;
330 m_collator = xCollator;
331
332 m_delegator->addGridDataListener( this );
333
334 m_isInitialized = true;
335 }
336
337
338 GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
339 {
340 GridDataEvent aEvent( i_originalEvent );
341 aEvent.Source = *const_cast< SortableGridDataModel* >( this );
342 aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
343 aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
344 return aEvent;
345 }
346
347
348 void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
349 GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
350 {
351 ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( cppu::UnoType<XGridDataListener>::get() );
352 if ( pListeners == nullptr )
353 return;
354
355 i_instanceLock.clear();
356 pListeners->notifyEach( i_listenerMethod, i_publicEvent );
357 }
358
359
360 void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event )
361 {
362 MethodGuard aGuard( *this, rBHelper );
363
364 if ( impl_isSorted_nothrow() )
365 {
366 // no infrastructure is in place currently to sort the new row to its proper location,
367 // so we remove the sorting here.
368 impl_removeColumnSort( aGuard );
369 aGuard.reset();
370 }
371
372 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
373 impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
374 }
375
376 void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
377 {
378 for ( auto& rIndex : io_indexMap )
379 {
380 if ( rIndex >= i_threshold )
381 --rIndex;
382 }
383 }
384
385 void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
386 {
387 OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
388
389 // clear the indexes
390 lcl_clear( m_publicToPrivateRowIndex );
391 lcl_clear( m_privateToPublicRowIndex );
392
393 // rebuild the index
394 if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
395 {
396 impl_removeColumnSort( i_instanceLock );
397 return;
398 }
399
400 // broadcast an artificial event, saying that all rows have been removed
401 GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
402 impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
403 i_instanceLock.reset();
404
405 // broadcast an artificial event, saying that n rows have been added
406 GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
407 impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
408 }
409
410
411 void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event )
412 {
413 MethodGuard aGuard( *this, rBHelper );
414
415 // if the data is not sorted, broadcast the event unchanged
416 if ( !impl_isSorted_nothrow() )
417 {
418 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
419 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
420 return;
421 }
422
423 // if all rows have been removed, also simply multiplex to own listeners
424 if ( i_event.FirstRow < 0 )
425 {
426 lcl_clear( m_publicToPrivateRowIndex );
427 lcl_clear( m_privateToPublicRowIndex );
428 GridDataEvent aEvent( i_event );
429 aEvent.Source = *this;
430 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
431 return;
432 }
433
434 bool needReIndex = false;
435 if ( i_event.FirstRow != i_event.LastRow )
436 {
437 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
438 needReIndex = true;
439 }
440 else if ( o3tl::make_unsigned( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
441 {
442 OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
443 needReIndex = true;
444 }
445
446 if ( needReIndex )
447 {
448 impl_rebuildIndexesAndNotify( aGuard );
449 return;
450 }
451
452 // build public event version
453 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
454
455 // remove the entries from the index maps
456 sal_Int32 const privateIndex = i_event.FirstRow;
457 sal_Int32 const publicIndex = aEvent.FirstRow;
458
459 m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
460 m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
461
462 // adjust remaining entries in the index maps
463 lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
464 lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
465
466 // broadcast the event
467 impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
468 }
469
470
471 void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event )
472 {
473 MethodGuard aGuard( *this, rBHelper );
474
475 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
476 impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
477 }
478
479
480 void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event )
481 {
482 MethodGuard aGuard( *this, rBHelper );
483
484 GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
485 impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
486 }
487
488
489 void SAL_CALL SortableGridDataModel::disposing( const EventObject& )
490 {
491 }
492
493 class CellDataLessComparison
494 {
495 public:
496 CellDataLessComparison(
497 ::std::vector< Any > const & i_data,
498 ::comphelper::IKeyPredicateLess const & i_predicate,
499 bool const i_sortAscending
500 )
501 :m_data( i_data )
502 ,m_predicate( i_predicate )
503 ,m_sortAscending( i_sortAscending )
504 {
505 }
506
507 bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
508 {
509 Any const & lhs = m_data[ i_lhs ];
510 Any const & rhs = m_data[ i_rhs ];
511 // <VOID/> is less than everything else
512 if ( !lhs.hasValue() )
513 return m_sortAscending;
514 if ( !rhs.hasValue() )
515 return !m_sortAscending;
516
517 // actually compare
518 if ( m_sortAscending )
519 return m_predicate.isLess( lhs, rhs );
520 else
521 return m_predicate.isLess( rhs, lhs );
522 }
523
524 private:
525 ::std::vector< Any > const & m_data;
526 ::comphelper::IKeyPredicateLess const & m_predicate;
527 bool const m_sortAscending;
528 };
529
530 bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending )
531 {
532 ::sal_Int32 const rowCount( getRowCount() );
533 ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
534
535 try
536 {
537 // build an unsorted translation table, and retrieve the unsorted data
538 ::std::vector< Any > aColumnData( rowCount );
539 Type dataType;
540 for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
541 {
542 aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
543 aPublicToPrivate[ rowIndex ] = rowIndex;
544
545 // determine the data types we assume for the complete column
546 if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
547 dataType = aColumnData[ rowIndex ].getValueType();
548 }
549
550 // get predicate object
551 ::std::unique_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
553 pPredicate, "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!");
554
555 // then sort
556 CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
557 ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
558 }
559 catch( const Exception& )
560 {
561 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
562 return false;
563 }
564
565 // also build the "private to public" mapping
566 ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
567 for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
568 aPrivateToPublic[ aPublicToPrivate[i] ] = i;
569
570 m_publicToPrivateRowIndex.swap( aPublicToPrivate );
571 m_privateToPublicRowIndex.swap( aPrivateToPublic );
572
573 return true;
574 }
575
576
577 void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, sal_Bool i_sortAscending )
578 {
579 MethodGuard aGuard( *this, rBHelper );
580
581 if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
582 throw IndexOutOfBoundsException( OUString(), *this );
583
584 if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
585 return;
586
587 m_currentSortColumn = i_columnIndex;
588 m_sortAscending = i_sortAscending;
589
590 impl_broadcast(
591 &XGridDataListener::dataChanged,
592 GridDataEvent( *this, -1, -1, -1, -1 ),
593 aGuard
594 );
595 }
596
597
598 void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
599 {
600 lcl_clear( m_publicToPrivateRowIndex );
601 lcl_clear( m_privateToPublicRowIndex );
602
603 m_currentSortColumn = -1;
604 m_sortAscending = true;
605 }
606
607
608 void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
609 {
610 impl_removeColumnSort_noBroadcast();
611 impl_broadcast(
612 &XGridDataListener::dataChanged,
613 GridDataEvent( *this, -1, -1, -1, -1 ),
614 i_instanceLock
615 );
616 }
617
618
619 void SAL_CALL SortableGridDataModel::removeColumnSort( )
620 {
621 MethodGuard aGuard( *this, rBHelper );
622 impl_removeColumnSort( aGuard );
623 }
624
625
626 css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( )
627 {
628 MethodGuard aGuard( *this, rBHelper );
629
630 return css::beans::Pair< ::sal_Int32, sal_Bool >( m_currentSortColumn, m_sortAscending );
631 }
632
633
634 void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
635 {
636 MethodGuard aGuard( *this, rBHelper );
637
638 Reference< XMutableGridDataModel > const delegator( m_delegator );
639 aGuard.clear();
640 delegator->addRow( i_heading, i_data );
641 }
642
643
644 void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
645 {
646 MethodGuard aGuard( *this, rBHelper );
647
648 Reference< XMutableGridDataModel > const delegator( m_delegator );
649 aGuard.clear();
650 delegator->addRows( i_headings, i_data );
651 }
652
653
654 void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
655 {
656 MethodGuard aGuard( *this, rBHelper );
657
658 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
659 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
660
661 Reference< XMutableGridDataModel > const delegator( m_delegator );
662 aGuard.clear();
663 delegator->insertRow( rowIndex, i_heading, i_data );
664 }
665
666
667 void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
668 {
669 MethodGuard aGuard( *this, rBHelper );
670
671 ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
672 // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
673
674 Reference< XMutableGridDataModel > const delegator( m_delegator );
675 aGuard.clear();
676 delegator->insertRows( rowIndex, i_headings, i_data );
677 }
678
679
680 void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
681 {
682 MethodGuard aGuard( *this, rBHelper );
683
684 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
685
686 Reference< XMutableGridDataModel > const delegator( m_delegator );
687 aGuard.clear();
688 delegator->removeRow( rowIndex );
689 }
690
691
692 void SAL_CALL SortableGridDataModel::removeAllRows( )
693 {
694 MethodGuard aGuard( *this, rBHelper );
695
696 Reference< XMutableGridDataModel > const delegator( m_delegator );
697 aGuard.clear();
698 delegator->removeAllRows();
699 }
700
701
702 void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
703 {
704 MethodGuard aGuard( *this, rBHelper );
705
706 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
707
708 Reference< XMutableGridDataModel > const delegator( m_delegator );
709 aGuard.clear();
710 delegator->updateCellData( i_columnIndex, rowIndex, i_value );
711 }
712
713
714 void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
715 {
716 MethodGuard aGuard( *this, rBHelper );
717
718 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
719
720 Reference< XMutableGridDataModel > const delegator( m_delegator );
721 aGuard.clear();
722 delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
723 }
724
725
726 void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
727 {
728 MethodGuard aGuard( *this, rBHelper );
729
730 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
731
732 Reference< XMutableGridDataModel > const delegator( m_delegator );
733 aGuard.clear();
734 delegator->updateRowHeading( rowIndex, i_heading );
735 }
736
737
738 void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
739 {
740 MethodGuard aGuard( *this, rBHelper );
741
742 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
743
744 Reference< XMutableGridDataModel > const delegator( m_delegator );
745 aGuard.clear();
746 delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
747 }
748
749
750 void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
751 {
752 MethodGuard aGuard( *this, rBHelper );
753
754 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
755
756 Reference< XMutableGridDataModel > const delegator( m_delegator );
757 aGuard.clear();
758 delegator->updateRowToolTip( rowIndex, i_value );
759 }
760
761
762 void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener )
763 {
764 rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
765 }
766
767
768 void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener )
769 {
770 rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
771 }
772
773
774 ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount()
775 {
776 MethodGuard aGuard( *this, rBHelper );
777
778 Reference< XMutableGridDataModel > const delegator( m_delegator );
779 aGuard.clear();
780 return delegator->getRowCount();
781 }
782
783
784 ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount()
785 {
786 MethodGuard aGuard( *this, rBHelper );
787
788 Reference< XMutableGridDataModel > const delegator( m_delegator );
789 aGuard.clear();
790 return delegator->getColumnCount();
791 }
792
793
794 Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
795 {
796 MethodGuard aGuard( *this, rBHelper );
797
798 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
799
800 Reference< XMutableGridDataModel > const delegator( m_delegator );
801 aGuard.clear();
802 return delegator->getCellData( i_columnIndex, rowIndex );
803 }
804
805
806 Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
807 {
808 MethodGuard aGuard( *this, rBHelper );
809
810 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
811
812 Reference< XMutableGridDataModel > const delegator( m_delegator );
813 aGuard.clear();
814 return delegator->getCellToolTip( i_columnIndex, rowIndex );
815 }
816
817
818 Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex )
819 {
820 MethodGuard aGuard( *this, rBHelper );
821
822 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
823
824 Reference< XMutableGridDataModel > const delegator( m_delegator );
825 aGuard.clear();
826 return delegator->getRowHeading( rowIndex );
827 }
828
829
830 Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
831 {
832 MethodGuard aGuard( *this, rBHelper );
833
834 ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
835
836 Reference< XMutableGridDataModel > const delegator( m_delegator );
837 aGuard.clear();
838 return delegator->getRowData( rowIndex );
839 }
840
841
842 void SAL_CALL SortableGridDataModel::disposing()
843 {
844 m_currentSortColumn = -1;
845
846 Reference< XComponent > const delegatorComponent( m_delegator );
847 m_delegator->removeGridDataListener( this );
848 m_delegator.clear();
849 delegatorComponent->dispose();
850
851 Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
852 m_collator.clear();
853 if ( collatorComponent.is() )
854 collatorComponent->dispose();
855
856 lcl_clear( m_publicToPrivateRowIndex );
857 lcl_clear( m_privateToPublicRowIndex );
858 }
859
860
861 Reference< css::util::XCloneable > SAL_CALL SortableGridDataModel::createClone( )
862 {
863 MethodGuard aGuard( *this, rBHelper );
864
865 return new SortableGridDataModel( *this );
866 }
867
868
869 OUString SAL_CALL SortableGridDataModel::getImplementationName( )
870 {
871 return "org.openoffice.comp.toolkit.SortableGridDataModel";
872 }
873
874 sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName )
875 {
876 return cppu::supportsService(this, i_serviceName);
877 }
878
879 Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( )
880 {
881 return { "com.sun.star.awt.grid.SortableGridDataModel" };
882 }
883
884
885 ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
886 {
887 if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
888 throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
889
890 if ( !impl_isSorted_nothrow() )
891 // no need to translate anything
892 return i_publicRowIndex;
893
894 ENSURE_OR_RETURN( o3tl::make_unsigned( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
895 "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
896 // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
897 // elements
898
899 return m_publicToPrivateRowIndex[ i_publicRowIndex ];
900 }
901
902
903 ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
904 {
905 if ( !impl_isSorted_nothrow() )
906 // no need to translate anything
907 return i_privateRowIndex;
908
909 if ( i_privateRowIndex < 0 )
910 return i_privateRowIndex;
911
912 ENSURE_OR_RETURN( o3tl::make_unsigned( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
913 "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
914
915 return m_privateToPublicRowIndex[ i_privateRowIndex ];
916 }
917
918}
919
920extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
922 css::uno::XComponentContext *context,
923 css::uno::Sequence<css::uno::Any> const &)
924{
925 return cppu::acquire(new SortableGridDataModel(context));
926}
927
928/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _ADOColumn Column
Reference< XComponentContext > m_xContext
AnyEventRef aEvent
static const AllSettings & GetSettings()
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
#define ENSURE_OR_RETURN_FALSE(c, m)
#define ENSURE_OR_THROW(c, m)
#define ENSURE_OR_RETURN(c, m, r)
#define DBG_UNHANDLED_EXCEPTION(...)
BitmapEx m_sortAscending
std::mutex m_aMutex
const LanguageTag & getLocale()
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
void dispose()
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
unsigned char sal_Bool
signed char sal_Int8