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 /** === begin UNO using === **/
38 using ::com::sun::star::uno::Reference
;
39 using ::com::sun::star::uno::RuntimeException
;
40 using ::com::sun::star::uno::Sequence
;
41 using ::com::sun::star::uno::UNO_QUERY_THROW
;
42 using ::com::sun::star::uno::UNO_QUERY
;
43 using ::com::sun::star::uno::XInterface
;
44 using ::com::sun::star::lang::XComponent
;
45 using ::com::sun::star::lang::EventObject
;
46 using ::com::sun::star::uno::Exception
;
47 using ::com::sun::star::util::XCloneable
;
48 /** === end UNO using === **/
50 using ::comphelper::stl_begin
;
51 using ::comphelper::stl_end
;
53 //==================================================================================================================
54 //= DefaultGridDataModel
55 //==================================================================================================================
56 //------------------------------------------------------------------------------------------------------------------
57 DefaultGridDataModel::DefaultGridDataModel()
58 :DefaultGridDataModel_Base( m_aMutex
)
64 //------------------------------------------------------------------------------------------------------------------
65 DefaultGridDataModel::DefaultGridDataModel( DefaultGridDataModel
const & i_copySource
)
67 ,DefaultGridDataModel_Base( m_aMutex
)
68 ,m_aData( i_copySource
.m_aData
)
69 ,m_aRowHeaders( i_copySource
.m_aRowHeaders
)
70 ,m_nColumnCount( i_copySource
.m_nColumnCount
)
74 //------------------------------------------------------------------------------------------------------------------
75 DefaultGridDataModel::~DefaultGridDataModel()
79 //------------------------------------------------------------------------------------------------------------------
80 void DefaultGridDataModel::broadcast( GridDataEvent
const & i_event
,
81 void ( SAL_CALL
XGridDataListener::*i_listenerMethod
)( GridDataEvent
const & ), ::comphelper::ComponentGuard
& i_instanceLock
)
83 ::cppu::OInterfaceContainerHelper
* pListeners
= rBHelper
.getContainer( XGridDataListener::static_type() );
87 i_instanceLock
.clear();
88 pListeners
->notifyEach( i_listenerMethod
, i_event
);
91 //------------------------------------------------------------------------------------------------------------------
92 ::sal_Int32 SAL_CALL
DefaultGridDataModel::getRowCount() throw (::com::sun::star::uno::RuntimeException
)
94 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
95 return impl_getRowCount_nolck();
98 //------------------------------------------------------------------------------------------------------------------
99 ::sal_Int32 SAL_CALL
DefaultGridDataModel::getColumnCount() throw (::com::sun::star::uno::RuntimeException
)
101 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
102 return m_nColumnCount
;
105 //------------------------------------------------------------------------------------------------------------------
106 DefaultGridDataModel::CellData
const & DefaultGridDataModel::impl_getCellData_throw( sal_Int32
const i_column
, sal_Int32
const i_row
) const
108 if ( ( i_row
< 0 ) || ( size_t( i_row
) > m_aData
.size() )
109 || ( i_column
< 0 ) || ( i_column
> m_nColumnCount
)
111 throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< DefaultGridDataModel
* >( this ) );
113 RowData
const & rRow( m_aData
[ i_row
] );
114 if ( size_t( i_column
) < rRow
.size() )
115 return rRow
[ i_column
];
117 static CellData s_aEmpty
;
121 //------------------------------------------------------------------------------------------------------------------
122 DefaultGridDataModel::RowData
& DefaultGridDataModel::impl_getRowDataAccess_throw( sal_Int32
const i_rowIndex
, size_t const i_requiredColumnCount
)
124 OSL_ENSURE( i_requiredColumnCount
<= size_t( m_nColumnCount
), "DefaultGridDataModel::impl_getRowDataAccess_throw: invalid column count!" );
125 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
126 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
128 RowData
& rRowData( m_aData
[ i_rowIndex
] );
129 if ( rRowData
.size() < i_requiredColumnCount
)
130 rRowData
.resize( i_requiredColumnCount
);
134 //------------------------------------------------------------------------------------------------------------------
135 DefaultGridDataModel::CellData
& DefaultGridDataModel::impl_getCellDataAccess_throw( sal_Int32
const i_columnIndex
, sal_Int32
const i_rowIndex
)
137 if ( ( i_columnIndex
< 0 ) || ( i_columnIndex
>= m_nColumnCount
) )
138 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
140 RowData
& rRowData( impl_getRowDataAccess_throw( i_rowIndex
, size_t( i_columnIndex
+ 1 ) ) );
141 return rRowData
[ i_columnIndex
];
144 //------------------------------------------------------------------------------------------------------------------
145 Any SAL_CALL
DefaultGridDataModel::getCellData( ::sal_Int32 i_column
, ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
147 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
148 return impl_getCellData_throw( i_column
, i_row
).first
;
151 //------------------------------------------------------------------------------------------------------------------
152 Any SAL_CALL
DefaultGridDataModel::getCellToolTip( ::sal_Int32 i_column
, ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
154 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
155 return impl_getCellData_throw( i_column
, i_row
).second
;
158 //------------------------------------------------------------------------------------------------------------------
159 Any SAL_CALL
DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row
) throw (RuntimeException
, IndexOutOfBoundsException
)
161 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
163 if ( ( i_row
< 0 ) || ( size_t( i_row
) >= m_aRowHeaders
.size() ) )
164 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
166 return m_aRowHeaders
[ i_row
];
169 //------------------------------------------------------------------------------------------------------------------
170 Sequence
< Any
> SAL_CALL
DefaultGridDataModel::getRowData( ::sal_Int32 i_rowIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
172 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
174 Sequence
< Any
> resultData( m_nColumnCount
);
175 RowData
& rRowData
= impl_getRowDataAccess_throw( i_rowIndex
, m_nColumnCount
);
177 ::std::transform( rRowData
.begin(), rRowData
.end(), resultData
.getArray(),
178 boost::bind(&CellData::first
,_1
));
182 //------------------------------------------------------------------------------------------------------------------
183 void DefaultGridDataModel::impl_insertRow( sal_Int32
const i_position
, Any
const & i_heading
, Sequence
< Any
> const & i_rowData
, sal_Int32
const i_assumedColCount
)
185 OSL_PRECOND( ( i_assumedColCount
<= 0 ) || ( i_assumedColCount
>= i_rowData
.getLength() ),
186 "DefaultGridDataModel::impl_insertRow: invalid column count!" );
189 m_aRowHeaders
.insert( m_aRowHeaders
.begin() + i_position
, i_heading
);
191 // create new data row
192 RowData
newRow( i_assumedColCount
> 0 ? i_assumedColCount
: i_rowData
.getLength() );
193 RowData::iterator cellData
= newRow
.begin();
194 for ( const Any
* pData
= stl_begin( i_rowData
); pData
!= stl_end( i_rowData
); ++pData
, ++cellData
)
195 cellData
->first
= *pData
;
198 m_aData
.insert( m_aData
.begin() + i_position
, newRow
);
201 //------------------------------------------------------------------------------------------------------------------
202 void SAL_CALL
DefaultGridDataModel::addRow( const Any
& i_heading
, const Sequence
< Any
>& i_data
) throw (RuntimeException
)
204 insertRow( getRowCount(), i_heading
, i_data
);
207 //------------------------------------------------------------------------------------------------------------------
208 void SAL_CALL
DefaultGridDataModel::addRows( const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
) throw (IllegalArgumentException
, RuntimeException
)
210 insertRows( getRowCount(), i_headings
, i_data
);
213 //------------------------------------------------------------------------------------------------------------------
214 void SAL_CALL
DefaultGridDataModel::insertRow( ::sal_Int32 i_index
, const Any
& i_heading
, const Sequence
< Any
>& i_data
) throw (RuntimeException
, IndexOutOfBoundsException
)
216 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
218 if ( ( i_index
< 0 ) || ( i_index
> impl_getRowCount_nolck() ) )
219 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
221 // actually insert the row
222 impl_insertRow( i_index
, i_heading
, i_data
);
224 // update column count
225 sal_Int32
const columnCount
= i_data
.getLength();
226 if ( columnCount
> m_nColumnCount
)
227 m_nColumnCount
= columnCount
;
230 GridDataEvent( *this, -1, -1, i_index
, i_index
),
231 &XGridDataListener::rowsInserted
,
236 //------------------------------------------------------------------------------------------------------------------
237 void SAL_CALL
DefaultGridDataModel::insertRows( ::sal_Int32 i_index
, const Sequence
< Any
>& i_headings
, const Sequence
< Sequence
< Any
> >& i_data
) throw (IllegalArgumentException
, IndexOutOfBoundsException
, RuntimeException
)
239 if ( i_headings
.getLength() != i_data
.getLength() )
240 throw IllegalArgumentException( ::rtl::OUString(), *this, -1 );
242 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
244 if ( ( i_index
< 0 ) || ( i_index
> impl_getRowCount_nolck() ) )
245 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
247 sal_Int32
const rowCount
= i_headings
.getLength();
251 // determine max col count in the new data
252 sal_Int32 maxColCount
= 0;
253 for ( sal_Int32 row
=0; row
<rowCount
; ++row
)
254 if ( i_data
[row
].getLength() > maxColCount
)
255 maxColCount
= i_data
[row
].getLength();
257 if ( maxColCount
< m_nColumnCount
)
258 maxColCount
= m_nColumnCount
;
260 for ( sal_Int32 row
=0; row
<rowCount
; ++row
)
262 impl_insertRow( i_index
+ row
, i_headings
[row
], i_data
[row
], maxColCount
);
265 if ( maxColCount
> m_nColumnCount
)
266 m_nColumnCount
= maxColCount
;
269 GridDataEvent( *this, -1, -1, i_index
, i_index
+ rowCount
- 1 ),
270 &XGridDataListener::rowsInserted
,
275 //------------------------------------------------------------------------------------------------------------------
276 void SAL_CALL
DefaultGridDataModel::removeRow( ::sal_Int32 i_rowIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
278 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
280 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
281 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
283 m_aRowHeaders
.erase( m_aRowHeaders
.begin() + i_rowIndex
);
284 m_aData
.erase( m_aData
.begin() + i_rowIndex
);
287 GridDataEvent( *this, -1, -1, i_rowIndex
, i_rowIndex
),
288 &XGridDataListener::rowsRemoved
,
293 //------------------------------------------------------------------------------------------------------------------
294 void SAL_CALL
DefaultGridDataModel::removeAllRows( ) throw (RuntimeException
)
296 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
298 m_aRowHeaders
.clear();
302 GridDataEvent( *this, -1, -1, -1, -1 ),
303 &XGridDataListener::rowsRemoved
,
308 //------------------------------------------------------------------------------------------------------------------
309 void SAL_CALL
DefaultGridDataModel::updateCellData( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
311 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
313 impl_getCellDataAccess_throw( i_columnIndex
, i_rowIndex
).first
= i_value
;
316 GridDataEvent( *this, i_columnIndex
, i_columnIndex
, i_rowIndex
, i_rowIndex
),
317 &XGridDataListener::dataChanged
,
322 //------------------------------------------------------------------------------------------------------------------
323 void SAL_CALL
DefaultGridDataModel::updateRowData( const Sequence
< ::sal_Int32
>& i_columnIndexes
, ::sal_Int32 i_rowIndex
, const Sequence
< Any
>& i_values
) throw (IndexOutOfBoundsException
, IllegalArgumentException
, RuntimeException
)
325 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
327 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aData
.size() ) )
328 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
330 if ( i_columnIndexes
.getLength() != i_values
.getLength() )
331 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
333 sal_Int32
const columnCount
= i_columnIndexes
.getLength();
334 if ( columnCount
== 0 )
337 for ( sal_Int32 col
= 0; col
< columnCount
; ++col
)
339 if ( ( i_columnIndexes
[col
] < 0 ) || ( i_columnIndexes
[col
] > m_nColumnCount
) )
340 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
343 RowData
& rDataRow
= m_aData
[ i_rowIndex
];
344 for ( sal_Int32 col
= 0; col
< columnCount
; ++col
)
346 sal_Int32
const columnIndex
= i_columnIndexes
[ col
];
347 if ( size_t( columnIndex
) >= rDataRow
.size() )
348 rDataRow
.resize( columnIndex
+ 1 );
350 rDataRow
[ columnIndex
].first
= i_values
[ col
];
353 sal_Int32
const firstAffectedColumn
= *::std::min_element( stl_begin( i_columnIndexes
), stl_end( i_columnIndexes
) );
354 sal_Int32
const lastAffectedColumn
= *::std::max_element( stl_begin( i_columnIndexes
), stl_end( i_columnIndexes
) );
356 GridDataEvent( *this, firstAffectedColumn
, lastAffectedColumn
, i_rowIndex
, i_rowIndex
),
357 &XGridDataListener::dataChanged
,
362 //------------------------------------------------------------------------------------------------------------------
363 void SAL_CALL
DefaultGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex
, const Any
& i_heading
) throw (IndexOutOfBoundsException
, RuntimeException
)
365 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
367 if ( ( i_rowIndex
< 0 ) || ( size_t( i_rowIndex
) >= m_aRowHeaders
.size() ) )
368 throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
370 m_aRowHeaders
[ i_rowIndex
] = i_heading
;
373 GridDataEvent( *this, -1, -1, i_rowIndex
, i_rowIndex
),
374 &XGridDataListener::rowHeadingChanged
,
379 //------------------------------------------------------------------------------------------------------------------
380 void SAL_CALL
DefaultGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex
, ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
382 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
383 impl_getCellDataAccess_throw( i_columnIndex
, i_rowIndex
).second
= i_value
;
386 //------------------------------------------------------------------------------------------------------------------
387 void SAL_CALL
DefaultGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex
, const Any
& i_value
) throw (IndexOutOfBoundsException
, RuntimeException
)
389 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
391 RowData
& rRowData
= impl_getRowDataAccess_throw( i_rowIndex
, m_nColumnCount
);
392 for ( RowData::iterator cell
= rRowData
.begin(); cell
!= rRowData
.end(); ++cell
)
393 cell
->second
= i_value
;
396 //------------------------------------------------------------------------------------------------------------------
397 void SAL_CALL
DefaultGridDataModel::addGridDataListener( const Reference
< grid::XGridDataListener
>& i_listener
) throw (RuntimeException
)
399 rBHelper
.addListener( XGridDataListener::static_type(), i_listener
);
402 //------------------------------------------------------------------------------------------------------------------
403 void SAL_CALL
DefaultGridDataModel::removeGridDataListener( const Reference
< grid::XGridDataListener
>& i_listener
) throw (RuntimeException
)
405 rBHelper
.removeListener( XGridDataListener::static_type(), i_listener
);
408 //------------------------------------------------------------------------------------------------------------------
409 void SAL_CALL
DefaultGridDataModel::disposing()
411 ::com::sun::star::lang::EventObject aEvent
;
412 aEvent
.Source
.set( *this );
413 rBHelper
.aLC
.disposeAndClear( aEvent
);
415 ::osl::MutexGuard
aGuard( m_aMutex
);
417 m_aData
.swap( aEmptyData
);
419 ::std::vector
< Any
> aEmptyRowHeaders
;
420 m_aRowHeaders
.swap( aEmptyRowHeaders
);
425 //------------------------------------------------------------------------------------------------------------------
426 ::rtl::OUString SAL_CALL
DefaultGridDataModel::getImplementationName( ) throw (RuntimeException
)
428 static const ::rtl::OUString
aImplName( RTL_CONSTASCII_USTRINGPARAM( "toolkit.DefaultGridDataModel" ) );
432 //------------------------------------------------------------------------------------------------------------------
433 sal_Bool SAL_CALL
DefaultGridDataModel::supportsService( const ::rtl::OUString
& ServiceName
) throw (RuntimeException
)
435 return ServiceName
.equalsAscii( szServiceName_DefaultGridDataModel
);
438 //------------------------------------------------------------------------------------------------------------------
439 Sequence
< ::rtl::OUString
> SAL_CALL
DefaultGridDataModel::getSupportedServiceNames( ) throw (RuntimeException
)
441 static const ::rtl::OUString
aServiceName( ::rtl::OUString::createFromAscii( szServiceName_DefaultGridDataModel
) );
442 static const Sequence
< ::rtl::OUString
> aSeq( &aServiceName
, 1 );
446 //------------------------------------------------------------------------------------------------------------------
447 Reference
< XCloneable
> SAL_CALL
DefaultGridDataModel::createClone( ) throw (RuntimeException
)
449 return new DefaultGridDataModel( *this );
452 //......................................................................................................................
453 } // namespace toolkit
454 //......................................................................................................................
456 Reference
< XInterface
> SAL_CALL
DefaultGridDataModel_CreateInstance( const Reference
< XMultiServiceFactory
>& )
458 return Reference
< XInterface
>( ( ::cppu::OWeakObject
* ) new ::toolkit::DefaultGridDataModel() );
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */