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 "defaultgriddatamodel.hxx"
23 #include <comphelper/stlunosequence.hxx>
24 #include <comphelper/componentguard.hxx>
25 #include <toolkit/helper/servicenames.hxx>
26 #include <tools/diagnose_ex.h>
27 #include <rtl/ref.hxx>
31 #include <boost/bind.hpp>
33 //......................................................................................................................
35 //......................................................................................................................
37 using ::com::sun::star::uno::Reference
;
38 using ::com::sun::star::uno::RuntimeException
;
39 using ::com::sun::star::uno::Sequence
;
40 using ::com::sun::star::uno::UNO_QUERY_THROW
;
41 using ::com::sun::star::uno::UNO_QUERY
;
42 using ::com::sun::star::uno::XInterface
;
43 using ::com::sun::star::lang::XComponent
;
44 using ::com::sun::star::lang::EventObject
;
45 using ::com::sun::star::uno::Exception
;
46 using ::com::sun::star::util::XCloneable
;
48 using ::comphelper::stl_begin
;
49 using ::comphelper::stl_end
;
51 //==================================================================================================================
52 //= DefaultGridDataModel
53 //==================================================================================================================
54 //------------------------------------------------------------------------------------------------------------------
55 DefaultGridDataModel::DefaultGridDataModel()
56 :DefaultGridDataModel_Base( m_aMutex
)
62 //------------------------------------------------------------------------------------------------------------------
63 DefaultGridDataModel::DefaultGridDataModel( DefaultGridDataModel
const & i_copySource
)
65 ,DefaultGridDataModel_Base( m_aMutex
)
66 ,m_aData( i_copySource
.m_aData
)
67 ,m_aRowHeaders( i_copySource
.m_aRowHeaders
)
68 ,m_nColumnCount( i_copySource
.m_nColumnCount
)
72 //------------------------------------------------------------------------------------------------------------------
73 DefaultGridDataModel::~DefaultGridDataModel()
77 //------------------------------------------------------------------------------------------------------------------
78 void DefaultGridDataModel::broadcast( GridDataEvent
const & i_event
,
79 void ( SAL_CALL
XGridDataListener::*i_listenerMethod
)( GridDataEvent
const & ), ::comphelper::ComponentGuard
& i_instanceLock
)
81 ::cppu::OInterfaceContainerHelper
* pListeners
= rBHelper
.getContainer( XGridDataListener::static_type() );
85 i_instanceLock
.clear();
86 pListeners
->notifyEach( i_listenerMethod
, i_event
);
89 //------------------------------------------------------------------------------------------------------------------
90 ::sal_Int32 SAL_CALL
DefaultGridDataModel::getRowCount() throw (::com::sun::star::uno::RuntimeException
)
92 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
93 return impl_getRowCount_nolck();
96 //------------------------------------------------------------------------------------------------------------------
97 ::sal_Int32 SAL_CALL
DefaultGridDataModel::getColumnCount() throw (::com::sun::star::uno::RuntimeException
)
99 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
100 return m_nColumnCount
;
103 //------------------------------------------------------------------------------------------------------------------
104 DefaultGridDataModel::CellData
const & DefaultGridDataModel::impl_getCellData_throw( sal_Int32
const i_column
, sal_Int32
const i_row
) const
106 if ( ( i_row
< 0 ) || ( size_t( i_row
) > m_aData
.size() )
107 || ( i_column
< 0 ) || ( i_column
> m_nColumnCount
)
109 throw IndexOutOfBoundsException( OUString(), *const_cast< DefaultGridDataModel
* >( this ) );
111 RowData
const & rRow( m_aData
[ i_row
] );
112 if ( size_t( i_column
) < rRow
.size() )
113 return rRow
[ i_column
];
115 static CellData s_aEmpty
;
119 //------------------------------------------------------------------------------------------------------------------
120 DefaultGridDataModel::RowData
& DefaultGridDataModel::impl_getRowDataAccess_throw( sal_Int32
const i_rowIndex
, size_t const i_requiredColumnCount
)
122 OSL_ENSURE( i_requiredColumnCount
<= size_t( m_nColumnCount
), "DefaultGridDataModel::impl_getRowDataAccess_throw: invalid column count!" );
123 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
124 throw IndexOutOfBoundsException( OUString(), *this );
126 RowData
& rRowData( m_aData
[ i_rowIndex
] );
127 if ( rRowData
.size() < i_requiredColumnCount
)
128 rRowData
.resize( i_requiredColumnCount
);
132 //------------------------------------------------------------------------------------------------------------------
133 DefaultGridDataModel::CellData
& DefaultGridDataModel::impl_getCellDataAccess_throw( sal_Int32
const i_columnIndex
, sal_Int32
const i_rowIndex
)
135 if ( ( i_columnIndex
< 0 ) || ( i_columnIndex
>= m_nColumnCount
) )
136 throw IndexOutOfBoundsException( OUString(), *this );
138 RowData
& rRowData( impl_getRowDataAccess_throw( i_rowIndex
, size_t( i_columnIndex
+ 1 ) ) );
139 return rRowData
[ i_columnIndex
];
142 //------------------------------------------------------------------------------------------------------------------
143 Any SAL_CALL
DefaultGridDataModel::getCellData( ::sal_Int32 i_column
, ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
145 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
146 return impl_getCellData_throw( i_column
, i_row
).first
;
149 //------------------------------------------------------------------------------------------------------------------
150 Any SAL_CALL
DefaultGridDataModel::getCellToolTip( ::sal_Int32 i_column
, ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
152 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
153 return impl_getCellData_throw( i_column
, i_row
).second
;
156 //------------------------------------------------------------------------------------------------------------------
157 Any SAL_CALL
DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
159 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
161 if ( ( i_row
< 0 ) || ( size_t( i_row
) >= m_aRowHeaders
.size() ) )
162 throw IndexOutOfBoundsException( OUString(), *this );
164 return m_aRowHeaders
[ i_row
];
167 //------------------------------------------------------------------------------------------------------------------
168 Sequence
< Any
> SAL_CALL
DefaultGridDataModel::getRowData( ::sal_Int32 i_rowIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
170 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
172 Sequence
< Any
> resultData( m_nColumnCount
);
173 RowData
& rRowData
= impl_getRowDataAccess_throw( i_rowIndex
, m_nColumnCount
);
175 ::std::transform( rRowData
.begin(), rRowData
.end(), resultData
.getArray(),
176 boost::bind(&CellData::first
,_1
));
180 //------------------------------------------------------------------------------------------------------------------
181 void DefaultGridDataModel::impl_insertRow( sal_Int32
const i_position
, Any
const & i_heading
, Sequence
< Any
> const & i_rowData
, sal_Int32
const i_assumedColCount
)
183 OSL_PRECOND( ( i_assumedColCount
<= 0 ) || ( i_assumedColCount
>= i_rowData
.getLength() ),
184 "DefaultGridDataModel::impl_insertRow: invalid column count!" );
187 m_aRowHeaders
.insert( m_aRowHeaders
.begin() + i_position
, i_heading
);
189 // create new data row
190 RowData
newRow( i_assumedColCount
> 0 ? i_assumedColCount
: i_rowData
.getLength() );
191 RowData::iterator cellData
= newRow
.begin();
192 for ( const Any
* pData
= stl_begin( i_rowData
); pData
!= stl_end( i_rowData
); ++pData
, ++cellData
)
193 cellData
->first
= *pData
;
196 m_aData
.insert( m_aData
.begin() + i_position
, newRow
);
199 //------------------------------------------------------------------------------------------------------------------
200 void SAL_CALL
DefaultGridDataModel::addRow( const Any
& i_heading
, const Sequence
< Any
>& i_data
) throw (RuntimeException
)
202 insertRow( getRowCount(), i_heading
, i_data
);
205 //------------------------------------------------------------------------------------------------------------------
206 void SAL_CALL
DefaultGridDataModel::addRows( const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
) throw (IllegalArgumentException
, RuntimeException
)
208 insertRows( getRowCount(), i_headings
, i_data
);
211 //------------------------------------------------------------------------------------------------------------------
212 void SAL_CALL
DefaultGridDataModel::insertRow( ::sal_Int32 i_index
, const Any
& i_heading
, const Sequence
< Any
>& i_data
) throw (RuntimeException
, IndexOutOfBoundsException
)
214 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
216 if ( ( i_index
< 0 ) || ( i_index
> impl_getRowCount_nolck() ) )
217 throw IndexOutOfBoundsException( OUString(), *this );
219 // actually insert the row
220 impl_insertRow( i_index
, i_heading
, i_data
);
222 // update column count
223 sal_Int32
const columnCount
= i_data
.getLength();
224 if ( columnCount
> m_nColumnCount
)
225 m_nColumnCount
= columnCount
;
228 GridDataEvent( *this, -1, -1, i_index
, i_index
),
229 &XGridDataListener::rowsInserted
,
234 //------------------------------------------------------------------------------------------------------------------
235 void SAL_CALL
DefaultGridDataModel::insertRows( ::sal_Int32 i_index
, const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
) throw (IllegalArgumentException
, IndexOutOfBoundsException
, RuntimeException
)
237 if ( i_headings
.getLength() != i_data
.getLength() )
238 throw IllegalArgumentException( OUString(), *this, -1 );
240 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
242 if ( ( i_index
< 0 ) || ( i_index
> impl_getRowCount_nolck() ) )
243 throw IndexOutOfBoundsException( OUString(), *this );
245 sal_Int32
const rowCount
= i_headings
.getLength();
249 // determine max col count in the new data
250 sal_Int32 maxColCount
= 0;
251 for ( sal_Int32 row
=0; row
<rowCount
; ++row
)
252 if ( i_data
[row
].getLength() > maxColCount
)
253 maxColCount
= i_data
[row
].getLength();
255 if ( maxColCount
< m_nColumnCount
)
256 maxColCount
= m_nColumnCount
;
258 for ( sal_Int32 row
=0; row
<rowCount
; ++row
)
260 impl_insertRow( i_index
+ row
, i_headings
[row
], i_data
[row
], maxColCount
);
263 if ( maxColCount
> m_nColumnCount
)
264 m_nColumnCount
= maxColCount
;
267 GridDataEvent( *this, -1, -1, i_index
, i_index
+ rowCount
- 1 ),
268 &XGridDataListener::rowsInserted
,
273 //------------------------------------------------------------------------------------------------------------------
274 void SAL_CALL
DefaultGridDataModel::removeRow( ::sal_Int32 i_rowIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
276 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
278 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
279 throw IndexOutOfBoundsException( OUString(), *this );
281 m_aRowHeaders
.erase( m_aRowHeaders
.begin() + i_rowIndex
);
282 m_aData
.erase( m_aData
.begin() + i_rowIndex
);
285 GridDataEvent( *this, -1, -1, i_rowIndex
, i_rowIndex
),
286 &XGridDataListener::rowsRemoved
,
291 //------------------------------------------------------------------------------------------------------------------
292 void SAL_CALL
DefaultGridDataModel::removeAllRows( ) throw (RuntimeException
)
294 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
296 m_aRowHeaders
.clear();
300 GridDataEvent( *this, -1, -1, -1, -1 ),
301 &XGridDataListener::rowsRemoved
,
306 //------------------------------------------------------------------------------------------------------------------
307 void SAL_CALL
DefaultGridDataModel::updateCellData( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
309 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
311 impl_getCellDataAccess_throw( i_columnIndex
, i_rowIndex
).first
= i_value
;
314 GridDataEvent( *this, i_columnIndex
, i_columnIndex
, i_rowIndex
, i_rowIndex
),
315 &XGridDataListener::dataChanged
,
320 //------------------------------------------------------------------------------------------------------------------
321 void SAL_CALL
DefaultGridDataModel::updateRowData( const Sequence
< ::sal_Int32
>& i_columnIndexes
, ::sal_Int32 i_rowIndex
, const Sequence
< Any
>& i_values
) throw (IndexOutOfBoundsException
, IllegalArgumentException
, RuntimeException
)
323 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
325 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
326 throw IndexOutOfBoundsException( OUString(), *this );
328 if ( i_columnIndexes
.getLength() != i_values
.getLength() )
329 throw IllegalArgumentException( OUString(), *this, 1 );
331 sal_Int32
const columnCount
= i_columnIndexes
.getLength();
332 if ( columnCount
== 0 )
335 for ( sal_Int32 col
= 0; col
< columnCount
; ++col
)
337 if ( ( i_columnIndexes
[col
] < 0 ) || ( i_columnIndexes
[col
] > m_nColumnCount
) )
338 throw IndexOutOfBoundsException( OUString(), *this );
341 RowData
& rDataRow
= m_aData
[ i_rowIndex
];
342 for ( sal_Int32 col
= 0; col
< columnCount
; ++col
)
344 sal_Int32
const columnIndex
= i_columnIndexes
[ col
];
345 if ( size_t( columnIndex
) >= rDataRow
.size() )
346 rDataRow
.resize( columnIndex
+ 1 );
348 rDataRow
[ columnIndex
].first
= i_values
[ col
];
351 sal_Int32
const firstAffectedColumn
= *::std::min_element( stl_begin( i_columnIndexes
), stl_end( i_columnIndexes
) );
352 sal_Int32
const lastAffectedColumn
= *::std::max_element( stl_begin( i_columnIndexes
), stl_end( i_columnIndexes
) );
354 GridDataEvent( *this, firstAffectedColumn
, lastAffectedColumn
, i_rowIndex
, i_rowIndex
),
355 &XGridDataListener::dataChanged
,
360 //------------------------------------------------------------------------------------------------------------------
361 void SAL_CALL
DefaultGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex
, const Any
& i_heading
) throw (IndexOutOfBoundsException
, RuntimeException
)
363 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
365 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aRowHeaders
.size() ) )
366 throw IndexOutOfBoundsException( OUString(), *this );
368 m_aRowHeaders
[ i_rowIndex
] = i_heading
;
371 GridDataEvent( *this, -1, -1, i_rowIndex
, i_rowIndex
),
372 &XGridDataListener::rowHeadingChanged
,
377 //------------------------------------------------------------------------------------------------------------------
378 void SAL_CALL
DefaultGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
380 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
381 impl_getCellDataAccess_throw( i_columnIndex
, i_rowIndex
).second
= i_value
;
384 //------------------------------------------------------------------------------------------------------------------
385 void SAL_CALL
DefaultGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
387 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
389 RowData
& rRowData
= impl_getRowDataAccess_throw( i_rowIndex
, m_nColumnCount
);
390 for ( RowData::iterator cell
= rRowData
.begin(); cell
!= rRowData
.end(); ++cell
)
391 cell
->second
= i_value
;
394 //------------------------------------------------------------------------------------------------------------------
395 void SAL_CALL
DefaultGridDataModel::addGridDataListener( const Reference
< grid::XGridDataListener
>& i_listener
) throw (RuntimeException
)
397 rBHelper
.addListener( XGridDataListener::static_type(), i_listener
);
400 //------------------------------------------------------------------------------------------------------------------
401 void SAL_CALL
DefaultGridDataModel::removeGridDataListener( const Reference
< grid::XGridDataListener
>& i_listener
) throw (RuntimeException
)
403 rBHelper
.removeListener( XGridDataListener::static_type(), i_listener
);
406 //------------------------------------------------------------------------------------------------------------------
407 void SAL_CALL
DefaultGridDataModel::disposing()
409 ::com::sun::star::lang::EventObject aEvent
;
410 aEvent
.Source
.set( *this );
411 rBHelper
.aLC
.disposeAndClear( aEvent
);
413 ::osl::MutexGuard
aGuard( m_aMutex
);
415 m_aData
.swap( aEmptyData
);
417 ::std::vector
< Any
> aEmptyRowHeaders
;
418 m_aRowHeaders
.swap( aEmptyRowHeaders
);
423 //------------------------------------------------------------------------------------------------------------------
424 OUString SAL_CALL
DefaultGridDataModel::getImplementationName( ) throw (RuntimeException
)
426 static const OUString
aImplName( "toolkit.DefaultGridDataModel" );
430 //------------------------------------------------------------------------------------------------------------------
431 sal_Bool SAL_CALL
DefaultGridDataModel::supportsService( const OUString
& ServiceName
) throw (RuntimeException
)
433 return ServiceName
.equalsAscii( szServiceName_DefaultGridDataModel
);
436 //------------------------------------------------------------------------------------------------------------------
437 Sequence
< OUString
> SAL_CALL
DefaultGridDataModel::getSupportedServiceNames( ) throw (RuntimeException
)
439 static const OUString
aServiceName( OUString::createFromAscii( szServiceName_DefaultGridDataModel
) );
440 static const Sequence
< OUString
> aSeq( &aServiceName
, 1 );
444 //------------------------------------------------------------------------------------------------------------------
445 Reference
< XCloneable
> SAL_CALL
DefaultGridDataModel::createClone( ) throw (RuntimeException
)
447 return new DefaultGridDataModel( *this );
450 //......................................................................................................................
451 } // namespace toolkit
452 //......................................................................................................................
454 Reference
< XInterface
> SAL_CALL
DefaultGridDataModel_CreateInstance( const Reference
< XMultiServiceFactory
>& )
456 return Reference
< XInterface
>( ( ::cppu::OWeakObject
* ) new ::toolkit::DefaultGridDataModel() );
459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */