Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 : : *
5 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
6 : : *
7 : : * OpenOffice.org - a multi-platform office productivity suite
8 : : *
9 : : * This file is part of OpenOffice.org.
10 : : *
11 : : * OpenOffice.org is free software: you can redistribute it and/or modify
12 : : * it under the terms of the GNU Lesser General Public License version 3
13 : : * only, as published by the Free Software Foundation.
14 : : *
15 : : * OpenOffice.org is distributed in the hope that it will be useful,
16 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : : * GNU Lesser General Public License version 3 for more details
19 : : * (a copy is included in the LICENSE file that accompanied this code).
20 : : *
21 : : * You should have received a copy of the GNU Lesser General Public License
22 : : * version 3 along with OpenOffice.org. If not, see
23 : : * <http://www.openoffice.org/license.html>
24 : : * for a copy of the LGPLv3 License.
25 : : *
26 : : ************************************************************************/
27 : :
28 : :
29 : : #include "sortablegriddatamodel.hxx"
30 : : #include "toolkit/helper/servicenames.hxx"
31 : :
32 : : #include <com/sun/star/i18n/XCollator.hpp>
33 : : #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 : : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
35 : :
36 : : #include <comphelper/anycompare.hxx>
37 : : #include <cppuhelper/typeprovider.hxx>
38 : : #include <tools/diagnose_ex.h>
39 : : #include <tools/debug.hxx>
40 : : #include <vcl/svapp.hxx>
41 : :
42 : : #include <set>
43 : :
44 : : //......................................................................................................................
45 : : namespace toolkit
46 : : {
47 : : //......................................................................................................................
48 : :
49 : : /** === begin UNO using === **/
50 : : using ::com::sun::star::uno::TypeClass;
51 : : using ::com::sun::star::uno::TypeClass_VOID;
52 : : using ::com::sun::star::uno::Reference;
53 : : using ::com::sun::star::uno::XInterface;
54 : : using ::com::sun::star::uno::UNO_QUERY;
55 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
56 : : using ::com::sun::star::uno::UNO_SET_THROW;
57 : : using ::com::sun::star::uno::Exception;
58 : : using ::com::sun::star::uno::RuntimeException;
59 : : using ::com::sun::star::uno::Any;
60 : : using ::com::sun::star::uno::makeAny;
61 : : using ::com::sun::star::uno::Sequence;
62 : : using ::com::sun::star::uno::Type;
63 : : using ::com::sun::star::lang::IndexOutOfBoundsException;
64 : : using ::com::sun::star::lang::IllegalArgumentException;
65 : : using ::com::sun::star::awt::grid::XGridDataListener;
66 : : using ::com::sun::star::beans::Pair;
67 : : using ::com::sun::star::util::XCloneable;
68 : : using ::com::sun::star::i18n::XCollator;
69 : : using ::com::sun::star::lang::IllegalArgumentException;
70 : : using ::com::sun::star::lang::XMultiServiceFactory;
71 : : using ::com::sun::star::awt::grid::GridDataEvent;
72 : : using ::com::sun::star::lang::EventObject;
73 : : using ::com::sun::star::ucb::AlreadyInitializedException;
74 : : /** === end UNO using === **/
75 : :
76 : : #ifdef DBG_UTIL
77 : : const char* SortableGridDataModel_checkInvariants( const void* _pInstance )
78 : : {
79 : : return static_cast< const SortableGridDataModel* >( _pInstance )->checkInvariants();
80 : : }
81 : :
82 : : //------------------------------------------------------------------------------------------------------------------
83 : : const char* SortableGridDataModel::checkInvariants() const
84 : : {
85 : : if ( m_publicToPrivateRowIndex.size() != m_privateToPublicRowIndex.size() )
86 : : return "inconsistent index maps";
87 : :
88 : : if ( m_delegator.is() )
89 : : {
90 : : if ( m_publicToPrivateRowIndex.size() != size_t( m_delegator->getRowCount() ) )
91 : : return "wrong cached row count";
92 : : }
93 : : else
94 : : {
95 : : if ( !m_publicToPrivateRowIndex.empty() )
96 : : return "disposed or not initialized, but having a non-empty map";
97 : : }
98 : :
99 : : for ( size_t publicIndex=0; publicIndex<m_publicToPrivateRowIndex.size(); ++publicIndex )
100 : : {
101 : : ::sal_Int32 const privateIndex = m_publicToPrivateRowIndex[ publicIndex ];
102 : : if ( ( privateIndex < 0 ) || ( size_t( privateIndex ) >= m_privateToPublicRowIndex.size() ) )
103 : : return "invalid cached private index";
104 : :
105 : : if ( m_privateToPublicRowIndex[ privateIndex ] != sal_Int32( publicIndex ) )
106 : : return "index map traversal not commutavive";
107 : : }
108 : :
109 : : if ( impl_isSorted_nothrow() && m_publicToPrivateRowIndex.empty() )
110 : : return "sorted, but no row index translation tables";
111 : :
112 : : if ( !impl_isSorted_nothrow() && !m_publicToPrivateRowIndex.empty() )
113 : : return "unsorted, but have index translation tables";
114 : :
115 : : return NULL;
116 : : }
117 : : #endif
118 : :
119 : : #define DBG_CHECK_ME() \
120 : : DBG_CHKTHIS( SortableGridDataModel, SortableGridDataModel_checkInvariants )
121 : :
122 : : //------------------------------------------------------------------------------------------------------------------
123 : : namespace
124 : : {
125 : : template< class STLCONTAINER >
126 : 4 : static void lcl_clear( STLCONTAINER& i_container )
127 : : {
128 [ + - ]: 4 : STLCONTAINER empty;
129 : 4 : empty.swap( i_container );
130 : 4 : }
131 : : }
132 : :
133 : : //==================================================================================================================
134 : : //= SortableGridDataModel
135 : : //==================================================================================================================
136 : : DBG_NAME( SortableGridDataModel )
137 : : //------------------------------------------------------------------------------------------------------------------
138 : 2 : SortableGridDataModel::SortableGridDataModel( Reference< XMultiServiceFactory > const & i_factory )
139 : : :SortableGridDataModel_Base( m_aMutex )
140 : : ,SortableGridDataModel_PrivateBase()
141 : : ,m_context( i_factory )
142 : : ,m_isInitialized( false )
143 : : ,m_delegator()
144 : : ,m_collator()
145 : : ,m_currentSortColumn( -1 )
146 : : ,m_sortAscending( true )
147 : : ,m_publicToPrivateRowIndex()
148 [ + - ][ + - ]: 2 : ,m_privateToPublicRowIndex()
[ + - ]
149 : : {
150 : : DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
151 : 2 : }
152 : :
153 : : //------------------------------------------------------------------------------------------------------------------
154 : 0 : SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
155 : : :cppu::BaseMutex()
156 : : ,SortableGridDataModel_Base( m_aMutex )
157 : : ,SortableGridDataModel_PrivateBase()
158 : : ,m_context( i_copySource.m_context )
159 : : ,m_isInitialized( true )
160 : : ,m_delegator()
161 : : ,m_collator( i_copySource.m_collator )
162 : : ,m_currentSortColumn( i_copySource.m_currentSortColumn )
163 : : ,m_sortAscending( i_copySource.m_sortAscending )
164 : : ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
165 [ # # ][ # # ]: 0 : ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
[ # # ]
166 : : {
167 : : DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
168 : :
169 [ # # ][ # # ]: 0 : ENSURE_OR_THROW( i_copySource.m_delegator.is(),
[ # # ][ # # ]
170 : : "not expected to be called for a disposed copy source!" );
171 [ # # ][ # # ]: 0 : m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
[ # # ]
172 : 0 : }
173 : :
174 : : //------------------------------------------------------------------------------------------------------------------
175 [ + - ][ + - ]: 2 : SortableGridDataModel::~SortableGridDataModel()
176 : : {
177 [ - + ]: 2 : if ( !rBHelper.bDisposed )
178 : : {
179 : 0 : acquire();
180 [ # # ]: 0 : dispose();
181 : : }
182 : :
183 : : DBG_DTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
184 [ - + ]: 4 : }
185 : :
186 : : //------------------------------------------------------------------------------------------------------------------
187 : 8 : Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType ) throw (RuntimeException)
188 : : {
189 : 8 : Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
190 [ - + ]: 8 : if ( !aReturn.hasValue() )
191 [ # # ]: 0 : aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
192 : 8 : return aReturn;
193 : : }
194 : :
195 : : //------------------------------------------------------------------------------------------------------------------
196 : 30 : void SAL_CALL SortableGridDataModel::acquire( ) throw ()
197 : : {
198 : 30 : SortableGridDataModel_Base::acquire();
199 : 30 : }
200 : :
201 : : //------------------------------------------------------------------------------------------------------------------
202 : 30 : void SAL_CALL SortableGridDataModel::release( ) throw ()
203 : : {
204 : 30 : SortableGridDataModel_Base::release();
205 : 30 : }
206 : :
207 : : //------------------------------------------------------------------------------------------------------------------
208 : 0 : Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( ) throw (RuntimeException)
209 : : {
210 : 0 : return SortableGridDataModel_Base::getTypes();
211 : : // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
212 : : }
213 : :
214 : : //------------------------------------------------------------------------------------------------------------------
215 : 0 : Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( ) throw (RuntimeException)
216 : : {
217 [ # # ][ # # ]: 0 : static ::cppu::OImplementationId aId;
218 : 0 : return aId.getImplementationId();
219 : : }
220 : :
221 : : //------------------------------------------------------------------------------------------------------------------
222 : : namespace
223 : : {
224 : 2 : Reference< XCollator > lcl_loadDefaultCollator_throw( ::comphelper::ComponentContext const & i_context )
225 : : {
226 [ + - ]: 2 : Reference< XCollator > const xCollator( i_context.createComponent( "com.sun.star.i18n.Collator" ), UNO_QUERY_THROW );
227 [ + - ][ + - ]: 2 : xCollator->loadDefaultCollator( Application::GetSettings().GetLocale(), 0 );
[ + - ][ + - ]
228 : 2 : return xCollator;
229 : : }
230 : : }
231 : :
232 : : //------------------------------------------------------------------------------------------------------------------
233 : 2 : void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments ) throw (Exception, RuntimeException)
234 : : {
235 [ + - ]: 2 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
236 : : DBG_CHECK_ME();
237 : :
238 [ - + ]: 2 : if ( m_delegator.is() )
239 [ # # ][ # # ]: 0 : throw AlreadyInitializedException( ::rtl::OUString(), *this );
240 : :
241 : 2 : Reference< XMutableGridDataModel > xDelegator;
242 : 2 : Reference< XCollator > xCollator;
243 [ + - - ]: 2 : switch ( i_arguments.getLength() )
244 : : {
245 : : case 1: // SortableGridDataModel.create( XMutableGridDataModel )
246 [ + - ]: 2 : xDelegator.set( i_arguments[0], UNO_QUERY );
247 [ + - ][ + - ]: 2 : xCollator = lcl_loadDefaultCollator_throw( m_context );
248 : 2 : break;
249 : :
250 : : case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
251 [ # # ]: 0 : xDelegator.set( i_arguments[0], UNO_QUERY );
252 [ # # ]: 0 : xCollator.set( i_arguments[1], UNO_QUERY );
253 [ # # ]: 0 : if ( !xCollator.is() )
254 [ # # ][ # # ]: 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 2 );
255 : 0 : break;
256 : : }
257 [ - + ]: 2 : if ( !xDelegator.is() )
258 [ # # ][ # # ]: 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
259 : :
260 [ + - ]: 2 : m_delegator = xDelegator;
261 [ + - ]: 2 : m_collator = xCollator;
262 : :
263 [ + - ][ + - ]: 2 : m_delegator->addGridDataListener( this );
[ + - ]
264 : :
265 [ + - ]: 2 : m_isInitialized = true;
266 : 2 : }
267 : :
268 : : //------------------------------------------------------------------------------------------------------------------
269 : 0 : GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
270 : : {
271 : 0 : GridDataEvent aEvent( i_originalEvent );
272 [ # # ][ # # ]: 0 : aEvent.Source = *const_cast< SortableGridDataModel* >( this );
273 [ # # ]: 0 : aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
274 [ # # ]: 0 : aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
275 : 0 : return aEvent;
276 : : }
277 : :
278 : : //------------------------------------------------------------------------------------------------------------------
279 : 0 : void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
280 : : GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
281 : : {
282 : 0 : ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( XGridDataListener::static_type() );
283 [ # # ]: 0 : if ( pListeners == NULL )
284 : 0 : return;
285 : :
286 : 0 : i_instanceLock.clear();
287 : 0 : pListeners->notifyEach( i_listenerMethod, i_publicEvent );
288 : : }
289 : :
290 : : //------------------------------------------------------------------------------------------------------------------
291 : 0 : void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event ) throw (RuntimeException)
292 : : {
293 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
294 : : DBG_CHECK_ME();
295 : :
296 : : // if the data is not sorted, broadcast the event unchanged
297 [ # # ]: 0 : if ( !impl_isSorted_nothrow() )
298 : : {
299 [ # # ]: 0 : GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
300 [ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
301 [ # # ]: 0 : return;
302 : : }
303 : :
304 : 0 : bool needReIndex = false;
305 [ # # ]: 0 : if ( i_event.FirstRow > i_event.LastRow )
306 : : {
307 : : OSL_ENSURE( false, "SortableGridDataModel::rowsInserted: invalid event - invalid row indexes!" );
308 : 0 : needReIndex = true;
309 : : }
310 [ # # ]: 0 : else if ( size_t( i_event.FirstRow ) > m_privateToPublicRowIndex.size() )
311 : : {
312 : : OSL_ENSURE( false, "SortableGridDataModel::rowsInserted: invalid event - too large row index!" );
313 : 0 : needReIndex = true;
314 : : }
315 : :
316 [ # # ]: 0 : if ( needReIndex )
317 : : {
318 [ # # ]: 0 : impl_rebuildIndexesAndNotify( aGuard );
319 : : return;
320 : : }
321 : :
322 : : // we do not insert the new rows into the sort order - if somebody adds rows while we're sorted, s/he has
323 : : // to resort. Instead, we simply append the rows, no matter where they were inserted in the delegator data
324 : : // model.
325 : 0 : sal_Int32 const nPublicFirstRow = sal_Int32( m_privateToPublicRowIndex.size() );
326 : 0 : sal_Int32 nPublicLastRow = nPublicFirstRow;
327 [ # # ]: 0 : for ( sal_Int32 newRow = i_event.FirstRow; newRow <= i_event.LastRow; ++newRow, ++nPublicLastRow )
328 : : {
329 [ # # ]: 0 : m_privateToPublicRowIndex.push_back( nPublicLastRow );
330 [ # # ]: 0 : m_publicToPrivateRowIndex.push_back( nPublicLastRow );
331 : : }
332 : :
333 : : // broadcast the event
334 [ # # ][ # # ]: 0 : GridDataEvent const aEvent( *this, -1, -1, nPublicFirstRow, nPublicLastRow );
335 [ # # ][ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
[ # # ][ # # ]
336 : : }
337 : :
338 : : //------------------------------------------------------------------------------------------------------------------
339 : : namespace
340 : : {
341 : 0 : void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
342 : : {
343 [ # # # # ]: 0 : for ( ::std::vector< ::sal_Int32 >::iterator loop = io_indexMap.begin();
[ # # ]
344 : 0 : loop != io_indexMap.end();
345 : : ++loop
346 : : )
347 : : {
348 [ # # ][ # # ]: 0 : if ( *loop >= i_threshold )
349 [ # # ]: 0 : --*loop;
350 : : }
351 : 0 : }
352 : : }
353 : :
354 : : //------------------------------------------------------------------------------------------------------------------
355 : 0 : void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
356 : : {
357 : : OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
358 : :
359 : : // clear the indexes
360 [ # # ]: 0 : lcl_clear( m_publicToPrivateRowIndex );
361 [ # # ]: 0 : lcl_clear( m_privateToPublicRowIndex );
362 : :
363 : : // broadcast an artificial event, saying that all rows have been removed
364 [ # # ][ # # ]: 0 : GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
365 [ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
366 [ # # ]: 0 : i_instanceLock.reset();
367 : :
368 : : // rebuild the index
369 [ # # ]: 0 : impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending );
370 : :
371 : : // broadcast an artificial event, saying that n rows have been added
372 [ # # ][ # # ]: 0 : GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
[ # # ][ # # ]
373 [ # # ][ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
[ # # ]
374 : 0 : }
375 : :
376 : : //------------------------------------------------------------------------------------------------------------------
377 : 0 : void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event ) throw (RuntimeException)
378 : : {
379 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
380 : : DBG_CHECK_ME();
381 : :
382 : : // if the data is not sorted, broadcast the event unchanged
383 [ # # ]: 0 : if ( !impl_isSorted_nothrow() )
384 : : {
385 [ # # ]: 0 : GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
386 [ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
387 [ # # ]: 0 : return;
388 : : }
389 : :
390 : : // if all rows have been removed, also simply multiplex to own listeners
391 [ # # ]: 0 : if ( i_event.FirstRow < 0 )
392 : : {
393 [ # # ]: 0 : lcl_clear( m_publicToPrivateRowIndex );
394 [ # # ]: 0 : lcl_clear( m_privateToPublicRowIndex );
395 [ # # ]: 0 : GridDataEvent aEvent( i_event );
396 [ # # ][ # # ]: 0 : aEvent.Source = *this;
397 [ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
398 [ # # ]: 0 : return;
399 : : }
400 : :
401 : 0 : bool needReIndex = false;
402 [ # # ]: 0 : if ( i_event.FirstRow != i_event.LastRow )
403 : : {
404 : : OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
405 : 0 : needReIndex = true;
406 : : }
407 [ # # ]: 0 : else if ( size_t( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
408 : : {
409 : : OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
410 : 0 : needReIndex = true;
411 : : }
412 : :
413 [ # # ]: 0 : if ( needReIndex )
414 : : {
415 [ # # ]: 0 : impl_rebuildIndexesAndNotify( aGuard );
416 : : return;
417 : : }
418 : :
419 : : // build public event version
420 [ # # ]: 0 : GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
421 : :
422 : : // remove the entries from the index maps
423 : 0 : sal_Int32 const privateIndex = i_event.FirstRow;
424 : 0 : sal_Int32 const publicIndex = aEvent.FirstRow;
425 : :
426 [ # # ][ # # ]: 0 : m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
427 [ # # ][ # # ]: 0 : m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
428 : :
429 : : // adjust remaining entries in the index maps
430 [ # # ]: 0 : lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
431 [ # # ]: 0 : lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
432 : :
433 : : // broadcast the event
434 [ # # ][ # # ]: 0 : impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
[ # # ][ # # ]
435 : : }
436 : :
437 : : //------------------------------------------------------------------------------------------------------------------
438 : 0 : void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event ) throw (RuntimeException)
439 : : {
440 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
441 : : DBG_CHECK_ME();
442 : :
443 [ # # ]: 0 : GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
444 [ # # ][ # # ]: 0 : impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
[ # # ]
445 : 0 : }
446 : :
447 : : //------------------------------------------------------------------------------------------------------------------
448 : 0 : void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event ) throw (RuntimeException)
449 : : {
450 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
451 : : DBG_CHECK_ME();
452 : :
453 [ # # ]: 0 : GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
454 [ # # ][ # # ]: 0 : impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
[ # # ]
455 : 0 : }
456 : :
457 : : //------------------------------------------------------------------------------------------------------------------
458 : 0 : void SAL_CALL SortableGridDataModel::disposing( const EventObject& i_event ) throw (RuntimeException)
459 : : {
460 : : // not interested in
461 : : OSL_UNUSED( i_event );
462 : 0 : }
463 : :
464 : : //------------------------------------------------------------------------------------------------------------------
465 : : namespace
466 : : {
467 : : class CellDataLessComparison : public ::std::binary_function< sal_Int32, sal_Int32, bool >
468 : : {
469 : : public:
470 : 0 : CellDataLessComparison(
471 : : ::std::vector< Any > const & i_data,
472 : : ::comphelper::IKeyPredicateLess& i_predicate,
473 : : sal_Bool const i_sortAscending
474 : : )
475 : : :m_data( i_data )
476 : : ,m_predicate( i_predicate )
477 : 0 : ,m_sortAscending( i_sortAscending )
478 : : {
479 : 0 : }
480 : :
481 : 0 : bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
482 : : {
483 : 0 : Any const & lhs = m_data[ i_lhs ];
484 : 0 : Any const & rhs = m_data[ i_rhs ];
485 : : // <VOID/> is less than everything else
486 [ # # ]: 0 : if ( !lhs.hasValue() )
487 : 0 : return m_sortAscending;
488 [ # # ]: 0 : if ( !rhs.hasValue() )
489 : 0 : return !m_sortAscending;
490 : :
491 : : // actually compare
492 [ # # ]: 0 : if ( m_sortAscending )
493 : 0 : return m_predicate.isLess( lhs, rhs );
494 : : else
495 : 0 : return m_predicate.isLess( rhs, lhs );
496 : : }
497 : :
498 : : private:
499 : : ::std::vector< Any > const & m_data;
500 : : ::comphelper::IKeyPredicateLess const & m_predicate;
501 : : sal_Bool const m_sortAscending;
502 : : };
503 : : }
504 : :
505 : : //------------------------------------------------------------------------------------------------------------------
506 : 0 : void SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, sal_Bool const i_sortAscending )
507 : : {
508 [ # # ]: 0 : ::sal_Int32 const rowCount( getRowCount() );
509 [ # # ]: 0 : ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
510 : :
511 : : try
512 : : {
513 : : // build an unsorted translation table, and retrieve the unsorted data
514 [ # # ]: 0 : ::std::vector< Any > aColumnData( rowCount );
515 : 0 : Type dataType;
516 [ # # ]: 0 : for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
517 : : {
518 [ # # ][ # # ]: 0 : aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
519 [ # # ]: 0 : aPublicToPrivate[ rowIndex ] = rowIndex;
520 : :
521 : : // determine the data types we assume for the complete column
522 [ # # ][ # # ]: 0 : if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
[ # # ]
523 : 0 : dataType = aColumnData[ rowIndex ].getValueType();
524 : : }
525 : :
526 : : // get predicate object
527 [ # # ][ # # ]: 0 : ::std::auto_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
528 [ # # ]: 0 : ENSURE_OR_RETURN_VOID( pPredicate.get(), "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!" );
529 : :
530 : : // then sort
531 : 0 : CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
532 [ # # ][ # # ]: 0 : ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
[ # # ]
[ # # # # ]
[ # # ]
533 : : }
534 [ # # ]: 0 : catch( const Exception& )
535 : : {
536 : : DBG_UNHANDLED_EXCEPTION();
537 : : return;
538 : : }
539 : :
540 : : // also build the "private to public" mapping
541 [ # # ]: 0 : ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
542 [ # # ]: 0 : for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
543 [ # # ][ # # ]: 0 : aPrivateToPublic[ aPublicToPrivate[i] ] = i;
544 : :
545 : 0 : m_publicToPrivateRowIndex.swap( aPublicToPrivate );
546 [ # # ]: 0 : m_privateToPublicRowIndex.swap( aPrivateToPublic );
547 : : }
548 : :
549 : : //------------------------------------------------------------------------------------------------------------------
550 : 0 : void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, ::sal_Bool i_sortAscending ) throw (IndexOutOfBoundsException, RuntimeException)
551 : : {
552 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
553 : : DBG_CHECK_ME();
554 : :
555 [ # # ][ # # ]: 0 : if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
[ # # ][ # # ]
556 [ # # ][ # # ]: 0 : throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
557 : :
558 [ # # ]: 0 : impl_reIndex_nothrow( i_columnIndex, i_sortAscending );
559 : :
560 : 0 : m_currentSortColumn = i_columnIndex;
561 : 0 : m_sortAscending = i_sortAscending;
562 : :
563 : : impl_broadcast(
564 : : &XGridDataListener::dataChanged,
565 : : GridDataEvent( *this, -1, -1, -1, -1 ),
566 : : aGuard
567 [ # # ][ # # ]: 0 : );
[ # # ][ # # ]
[ # # ]
568 : 0 : }
569 : :
570 : : //------------------------------------------------------------------------------------------------------------------
571 : 0 : void SAL_CALL SortableGridDataModel::removeColumnSort( ) throw (RuntimeException)
572 : : {
573 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
574 : : DBG_CHECK_ME();
575 : :
576 [ # # ]: 0 : lcl_clear( m_publicToPrivateRowIndex );
577 [ # # ]: 0 : lcl_clear( m_privateToPublicRowIndex );
578 : :
579 : 0 : m_currentSortColumn = -1;
580 : 0 : m_sortAscending = sal_True;
581 : :
582 : : impl_broadcast(
583 : : &XGridDataListener::dataChanged,
584 : : GridDataEvent( *this, -1, -1, -1, -1 ),
585 : : aGuard
586 [ # # ][ # # ]: 0 : );
[ # # ][ # # ]
[ # # ]
587 : 0 : }
588 : :
589 : : //------------------------------------------------------------------------------------------------------------------
590 : 0 : Pair< ::sal_Int32, ::sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( ) throw (RuntimeException)
591 : : {
592 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
593 : : DBG_CHECK_ME();
594 : :
595 [ # # ]: 0 : return Pair< ::sal_Int32, ::sal_Bool >( m_currentSortColumn, m_sortAscending );
596 : : }
597 : :
598 : : //------------------------------------------------------------------------------------------------------------------
599 : 0 : void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException)
600 : : {
601 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
602 : : DBG_CHECK_ME();
603 : :
604 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
605 [ # # ]: 0 : aGuard.clear();
606 [ # # ][ # # ]: 0 : delegator->addRow( i_heading, i_data );
[ # # ]
607 : 0 : }
608 : :
609 : : //------------------------------------------------------------------------------------------------------------------
610 : 0 : void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, RuntimeException)
611 : : {
612 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
613 : : DBG_CHECK_ME();
614 : :
615 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
616 [ # # ]: 0 : aGuard.clear();
617 [ # # ][ # # ]: 0 : delegator->addRows( i_headings, i_data );
[ # # ]
618 : 0 : }
619 : :
620 : : //------------------------------------------------------------------------------------------------------------------
621 : 0 : void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
622 : : {
623 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
624 : : DBG_CHECK_ME();
625 : :
626 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
627 : :
628 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
629 [ # # ]: 0 : aGuard.clear();
630 [ # # ][ # # ]: 0 : delegator->removeRow( rowIndex );
[ # # ]
631 : 0 : }
632 : :
633 : : //------------------------------------------------------------------------------------------------------------------
634 : 0 : void SAL_CALL SortableGridDataModel::removeAllRows( ) throw (RuntimeException)
635 : : {
636 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
637 : : DBG_CHECK_ME();
638 : :
639 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
640 [ # # ]: 0 : aGuard.clear();
641 [ # # ][ # # ]: 0 : delegator->removeAllRows();
[ # # ]
642 : 0 : }
643 : :
644 : : //------------------------------------------------------------------------------------------------------------------
645 : 0 : void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
646 : : {
647 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
648 : : DBG_CHECK_ME();
649 : :
650 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
651 : :
652 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
653 [ # # ]: 0 : aGuard.clear();
654 [ # # ][ # # ]: 0 : delegator->updateCellData( i_columnIndex, rowIndex, i_value );
[ # # ]
655 : 0 : }
656 : :
657 : : //------------------------------------------------------------------------------------------------------------------
658 : 0 : void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
659 : : {
660 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
661 : : DBG_CHECK_ME();
662 : :
663 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
664 : :
665 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
666 [ # # ]: 0 : aGuard.clear();
667 [ # # ][ # # ]: 0 : delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
[ # # ]
668 : 0 : }
669 : :
670 : : //------------------------------------------------------------------------------------------------------------------
671 : 0 : void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading ) throw (IndexOutOfBoundsException, RuntimeException)
672 : : {
673 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
674 : : DBG_CHECK_ME();
675 : :
676 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
677 : :
678 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
679 [ # # ]: 0 : aGuard.clear();
680 [ # # ][ # # ]: 0 : delegator->updateRowHeading( rowIndex, i_heading );
[ # # ]
681 : 0 : }
682 : :
683 : : //------------------------------------------------------------------------------------------------------------------
684 : 0 : void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
685 : : {
686 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
687 : : DBG_CHECK_ME();
688 : :
689 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
690 : :
691 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
692 [ # # ]: 0 : aGuard.clear();
693 [ # # ][ # # ]: 0 : delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
[ # # ]
694 : 0 : }
695 : :
696 : : //------------------------------------------------------------------------------------------------------------------
697 : 0 : void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
698 : : {
699 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
700 : : DBG_CHECK_ME();
701 : :
702 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
703 : :
704 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
705 [ # # ]: 0 : aGuard.clear();
706 [ # # ][ # # ]: 0 : delegator->updateRowToolTip( rowIndex, i_value );
[ # # ]
707 : 0 : }
708 : :
709 : : //------------------------------------------------------------------------------------------------------------------
710 : 0 : void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
711 : : {
712 : 0 : rBHelper.addListener( XGridDataListener::static_type(), i_listener );
713 : 0 : }
714 : :
715 : : //------------------------------------------------------------------------------------------------------------------
716 : 0 : void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener ) throw (RuntimeException)
717 : : {
718 : 0 : rBHelper.removeListener( XGridDataListener::static_type(), i_listener );
719 : 0 : }
720 : :
721 : : //------------------------------------------------------------------------------------------------------------------
722 : 0 : ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount() throw (RuntimeException)
723 : : {
724 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
725 : : DBG_CHECK_ME();
726 : :
727 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
728 [ # # ]: 0 : aGuard.clear();
729 [ # # ][ # # ]: 0 : return delegator->getRowCount();
[ # # ]
730 : : }
731 : :
732 : : //------------------------------------------------------------------------------------------------------------------
733 : 0 : ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount() throw (RuntimeException)
734 : : {
735 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
736 : : DBG_CHECK_ME();
737 : :
738 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
739 [ # # ]: 0 : aGuard.clear();
740 [ # # ][ # # ]: 0 : return delegator->getColumnCount();
[ # # ]
741 : : }
742 : :
743 : : //------------------------------------------------------------------------------------------------------------------
744 : 0 : Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
745 : : {
746 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
747 : : DBG_CHECK_ME();
748 : :
749 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
750 : :
751 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
752 [ # # ]: 0 : aGuard.clear();
753 [ # # ][ # # ]: 0 : return delegator->getCellData( i_columnIndex, rowIndex );
[ # # ]
754 : : }
755 : :
756 : : //------------------------------------------------------------------------------------------------------------------
757 : 0 : Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
758 : : {
759 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
760 : : DBG_CHECK_ME();
761 : :
762 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
763 : :
764 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
765 [ # # ]: 0 : aGuard.clear();
766 [ # # ][ # # ]: 0 : return delegator->getCellToolTip( i_columnIndex, rowIndex );
[ # # ]
767 : : }
768 : :
769 : : //------------------------------------------------------------------------------------------------------------------
770 : 0 : Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
771 : : {
772 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
773 : : DBG_CHECK_ME();
774 : :
775 [ # # ]: 0 : ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
776 : :
777 : 0 : Reference< XMutableGridDataModel > const delegator( m_delegator );
778 [ # # ]: 0 : aGuard.clear();
779 [ # # ][ # # ]: 0 : return delegator->getRowHeading( rowIndex );
[ # # ]
780 : : }
781 : :
782 : : //------------------------------------------------------------------------------------------------------------------
783 : 2 : void SAL_CALL SortableGridDataModel::disposing()
784 : : {
785 : 2 : m_currentSortColumn = -1;
786 : :
787 [ + - ][ + - ]: 2 : Reference< XComponent > const delegatorComponent( m_delegator.get() );
788 [ + - ][ + - ]: 2 : m_delegator->removeGridDataListener( this );
[ + - ]
789 : 2 : m_delegator.clear();
790 [ + - ][ + - ]: 2 : delegatorComponent->dispose();
791 : :
792 [ + - ]: 2 : Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
793 : 2 : m_collator.clear();
794 [ - + ]: 2 : if ( collatorComponent.is() )
795 [ # # ][ # # ]: 0 : collatorComponent->dispose();
796 : :
797 [ + - ]: 2 : lcl_clear( m_publicToPrivateRowIndex );
798 [ + - ]: 2 : lcl_clear( m_privateToPublicRowIndex );
799 : 2 : }
800 : :
801 : : //------------------------------------------------------------------------------------------------------------------
802 : 0 : Reference< XCloneable > SAL_CALL SortableGridDataModel::createClone( ) throw (RuntimeException)
803 : : {
804 [ # # ]: 0 : MethodGuard aGuard( *this, rBHelper );
805 : : DBG_CHECK_ME();
806 : :
807 [ # # ][ # # ]: 0 : return new SortableGridDataModel( *this );
[ # # ][ # # ]
808 : : }
809 : :
810 : : //------------------------------------------------------------------------------------------------------------------
811 : 0 : ::rtl::OUString SAL_CALL SortableGridDataModel::getImplementationName( ) throw (RuntimeException)
812 : : {
813 : 0 : return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.toolkit.SortableGridDataModel" ) );
814 : : }
815 : :
816 : : //------------------------------------------------------------------------------------------------------------------
817 : 0 : ::sal_Bool SAL_CALL SortableGridDataModel::supportsService( const ::rtl::OUString& i_serviceName ) throw (RuntimeException)
818 : : {
819 [ # # ]: 0 : Sequence< ::rtl::OUString > const aServiceNames( getSupportedServiceNames() );
820 [ # # ]: 0 : for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i )
821 [ # # ]: 0 : if ( aServiceNames[i] == i_serviceName )
822 : 0 : return sal_True;
823 [ # # ]: 0 : return sal_False;
824 : : }
825 : :
826 : : //------------------------------------------------------------------------------------------------------------------
827 : 0 : Sequence< ::rtl::OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( ) throw (RuntimeException)
828 : : {
829 : 0 : Sequence< ::rtl::OUString > aServiceNames(1);
830 [ # # ]: 0 : aServiceNames[0] = ::rtl::OUString::createFromAscii( szServiceName_SortableGridDataModel );
831 : 0 : return aServiceNames;
832 : : }
833 : :
834 : : //------------------------------------------------------------------------------------------------------------------
835 : 0 : ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
836 : : {
837 [ # # ][ # # ]: 0 : if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
[ # # ]
838 [ # # ][ # # ]: 0 : throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SortableGridDataModel* >( this ) );
839 : :
840 [ # # ]: 0 : if ( !impl_isSorted_nothrow() )
841 : : // no need to translate anything
842 : 0 : return i_publicRowIndex;
843 : :
844 [ # # ]: 0 : ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
845 : : "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
846 : : // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
847 : : // elements
848 : :
849 : 0 : return m_publicToPrivateRowIndex[ i_publicRowIndex ];
850 : : }
851 : :
852 : : //------------------------------------------------------------------------------------------------------------------
853 : 0 : ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
854 : : {
855 [ # # ]: 0 : if ( !impl_isSorted_nothrow() )
856 : : // no need to translate anything
857 : 0 : return i_privateRowIndex;
858 : :
859 [ # # ]: 0 : if ( i_privateRowIndex < 0 )
860 : 0 : return i_privateRowIndex;
861 : :
862 [ # # ]: 0 : ENSURE_OR_RETURN( size_t( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
863 : : "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
864 : :
865 : 0 : return m_privateToPublicRowIndex[ i_privateRowIndex ];
866 : : }
867 : :
868 : : //......................................................................................................................
869 : : } // namespace toolkit
870 : : //......................................................................................................................
871 : :
872 : 2 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SortableGridDataModel_CreateInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory )
873 : : {
874 [ + - ]: 2 : return *( new ::toolkit::SortableGridDataModel( i_factory ) );
875 : : }
876 : :
877 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|