/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_toolkit.hxx" #include "defaultgriddatamodel.hxx" #include #include #include #include #include #include #include //...................................................................................................................... namespace toolkit //...................................................................................................................... { /** === begin UNO using === **/ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::XInterface; using ::com::sun::star::lang::XComponent; using ::com::sun::star::lang::EventObject; using ::com::sun::star::uno::Exception; using ::com::sun::star::util::XCloneable; /** === end UNO using === **/ using ::comphelper::stl_begin; using ::comphelper::stl_end; //================================================================================================================== //= DefaultGridDataModel //================================================================================================================== //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::DefaultGridDataModel() :DefaultGridDataModel_Base( m_aMutex ) ,m_aRowHeaders() ,m_nColumnCount(0) { } //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::DefaultGridDataModel( DefaultGridDataModel const & i_copySource ) :cppu::BaseMutex() ,DefaultGridDataModel_Base( m_aMutex ) ,m_aData( i_copySource.m_aData ) ,m_aRowHeaders( i_copySource.m_aRowHeaders ) ,m_nColumnCount( i_copySource.m_nColumnCount ) { } //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::~DefaultGridDataModel() { } //------------------------------------------------------------------------------------------------------------------ void DefaultGridDataModel::broadcast( GridDataEvent const & i_event, void ( SAL_CALL XGridDataListener::*i_listenerMethod )( GridDataEvent const & ), ::comphelper::ComponentGuard & i_instanceLock ) { ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( XGridDataListener::static_type() ); if ( !pListeners ) return; i_instanceLock.clear(); pListeners->notifyEach( i_listenerMethod, i_event ); } //------------------------------------------------------------------------------------------------------------------ ::sal_Int32 SAL_CALL DefaultGridDataModel::getRowCount() throw (::com::sun::star::uno::RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); return impl_getRowCount_nolck(); } //------------------------------------------------------------------------------------------------------------------ ::sal_Int32 SAL_CALL DefaultGridDataModel::getColumnCount() throw (::com::sun::star::uno::RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); return m_nColumnCount; } //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::CellData const & DefaultGridDataModel::impl_getCellData_throw( sal_Int32 const i_column, sal_Int32 const i_row ) const { if ( ( i_row < 0 ) || ( size_t( i_row ) > m_aData.size() ) || ( i_column < 0 ) || ( i_column > m_nColumnCount ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< DefaultGridDataModel* >( this ) ); RowData const & rRow( m_aData[ i_row ] ); if ( size_t( i_column ) < rRow.size() ) return rRow[ i_column ]; static CellData s_aEmpty; return s_aEmpty; } //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::RowData& DefaultGridDataModel::impl_getRowDataAccess_throw( sal_Int32 const i_rowIndex, size_t const i_requiredColumnCount ) { OSL_ENSURE( i_requiredColumnCount <= size_t( m_nColumnCount ), "DefaultGridDataModel::impl_getRowDataAccess_throw: invalid column count!" ); if ( ( i_rowIndex < 0 ) || ( size_t( i_rowIndex ) >= m_aData.size() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); RowData& rRowData( m_aData[ i_rowIndex ] ); if ( rRowData.size() < i_requiredColumnCount ) rRowData.resize( i_requiredColumnCount ); return rRowData; } //------------------------------------------------------------------------------------------------------------------ DefaultGridDataModel::CellData& DefaultGridDataModel::impl_getCellDataAccess_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex ) { if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= m_nColumnCount ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); RowData& rRowData( impl_getRowDataAccess_throw( i_rowIndex, size_t( i_columnIndex + 1 ) ) ); return rRowData[ i_columnIndex ]; } //------------------------------------------------------------------------------------------------------------------ Any SAL_CALL DefaultGridDataModel::getCellData( ::sal_Int32 i_column, ::sal_Int32 i_row ) throw (RuntimeException, IndexOutOfBoundsException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); return impl_getCellData_throw( i_column, i_row ).first; } //------------------------------------------------------------------------------------------------------------------ Any SAL_CALL DefaultGridDataModel::getCellToolTip( ::sal_Int32 i_column, ::sal_Int32 i_row ) throw (RuntimeException, IndexOutOfBoundsException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); return impl_getCellData_throw( i_column, i_row ).second; } //------------------------------------------------------------------------------------------------------------------ Any SAL_CALL DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row ) throw (RuntimeException, IndexOutOfBoundsException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_row < 0 ) || ( size_t( i_row ) >= m_aRowHeaders.size() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); return m_aRowHeaders[ i_row ]; } //------------------------------------------------------------------------------------------------------------------ Sequence< Any > SAL_CALL DefaultGridDataModel::getRowData( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); Sequence< Any > resultData( m_nColumnCount ); RowData& rRowData = impl_getRowDataAccess_throw( i_rowIndex, m_nColumnCount ); ::std::transform( rRowData.begin(), rRowData.end(), resultData.getArray(), ::std::select1st< CellData >() ); return resultData; } //------------------------------------------------------------------------------------------------------------------ void DefaultGridDataModel::impl_insertRow( sal_Int32 const i_position, Any const & i_heading, Sequence< Any > const & i_rowData, sal_Int32 const i_assumedColCount ) { OSL_PRECOND( ( i_assumedColCount <= 0 ) || ( i_assumedColCount >= i_rowData.getLength() ), "DefaultGridDataModel::impl_insertRow: invalid column count!" ); // insert heading m_aRowHeaders.insert( m_aRowHeaders.begin() + i_position, i_heading ); // create new data row RowData newRow( i_assumedColCount > 0 ? i_assumedColCount : i_rowData.getLength() ); RowData::iterator cellData = newRow.begin(); for ( const Any* pData = stl_begin( i_rowData ); pData != stl_end( i_rowData ); ++pData, ++cellData ) cellData->first = *pData; // insert data row m_aData.insert( m_aData.begin() + i_position, newRow ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException) { insertRow( getRowCount(), i_heading, i_data ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, RuntimeException) { insertRows( getRowCount(), i_headings, i_data ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException, IndexOutOfBoundsException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); // actually insert the row impl_insertRow( i_index, i_heading, i_data ); // update column count sal_Int32 const columnCount = i_data.getLength(); if ( columnCount > m_nColumnCount ) m_nColumnCount = columnCount; broadcast( GridDataEvent( *this, -1, -1, i_index, i_index ), &XGridDataListener::rowsInserted, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, IndexOutOfBoundsException, RuntimeException) { if ( i_headings.getLength() != i_data.getLength() ) throw IllegalArgumentException( ::rtl::OUString(), *this, -1 ); ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); sal_Int32 const rowCount = i_headings.getLength(); if ( rowCount == 0 ) return; // determine max col count in the new data sal_Int32 maxColCount = 0; for ( sal_Int32 row=0; row maxColCount ) maxColCount = i_data[row].getLength(); if ( maxColCount < m_nColumnCount ) maxColCount = m_nColumnCount; for ( sal_Int32 row=0; row m_nColumnCount ) m_nColumnCount = maxColCount; broadcast( GridDataEvent( *this, -1, -1, i_index, i_index + rowCount - 1 ), &XGridDataListener::rowsInserted, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::removeRow( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_rowIndex < 0 ) || ( size_t( i_rowIndex ) >= m_aData.size() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); m_aRowHeaders.erase( m_aRowHeaders.begin() + i_rowIndex ); m_aData.erase( m_aData.begin() + i_rowIndex ); broadcast( GridDataEvent( *this, -1, -1, i_rowIndex, i_rowIndex ), &XGridDataListener::rowsRemoved, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::removeAllRows( ) throw (RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); m_aRowHeaders.clear(); m_aData.clear(); broadcast( GridDataEvent( *this, -1, -1, -1, -1 ), &XGridDataListener::rowsRemoved, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); impl_getCellDataAccess_throw( i_columnIndex, i_rowIndex ).first = i_value; broadcast( GridDataEvent( *this, i_columnIndex, i_columnIndex, i_rowIndex, i_rowIndex ), &XGridDataListener::dataChanged, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_rowIndex < 0 ) || ( size_t( i_rowIndex ) >= m_aData.size() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); if ( i_columnIndexes.getLength() != i_values.getLength() ) throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); sal_Int32 const columnCount = i_columnIndexes.getLength(); if ( columnCount == 0 ) return; for ( sal_Int32 col = 0; col < columnCount; ++col ) { if ( ( i_columnIndexes[col] < 0 ) || ( i_columnIndexes[col] > m_nColumnCount ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); } RowData& rDataRow = m_aData[ i_rowIndex ]; for ( sal_Int32 col = 0; col < columnCount; ++col ) { sal_Int32 const columnIndex = i_columnIndexes[ col ]; if ( size_t( columnIndex ) >= rDataRow.size() ) rDataRow.resize( columnIndex + 1 ); rDataRow[ columnIndex ].first = i_values[ col ]; } sal_Int32 const firstAffectedColumn = *::std::min_element( stl_begin( i_columnIndexes ), stl_end( i_columnIndexes ) ); sal_Int32 const lastAffectedColumn = *::std::max_element( stl_begin( i_columnIndexes ), stl_end( i_columnIndexes ) ); broadcast( GridDataEvent( *this, firstAffectedColumn, lastAffectedColumn, i_rowIndex, i_rowIndex ), &XGridDataListener::dataChanged, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); if ( ( i_rowIndex < 0 ) || ( size_t( i_rowIndex ) >= m_aRowHeaders.size() ) ) throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); m_aRowHeaders[ i_rowIndex ] = i_heading; broadcast( GridDataEvent( *this, -1, -1, i_rowIndex, i_rowIndex ), &XGridDataListener::rowHeadingChanged, aGuard ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); impl_getCellDataAccess_throw( i_columnIndex, i_rowIndex ).second = i_value; } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException) { ::comphelper::ComponentGuard aGuard( *this, rBHelper ); RowData& rRowData = impl_getRowDataAccess_throw( i_rowIndex, m_nColumnCount ); for ( RowData::iterator cell = rRowData.begin(); cell != rRowData.end(); ++cell ) cell->second = i_value; } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::addGridDataListener( const Reference< grid::XGridDataListener >& i_listener ) throw (RuntimeException) { rBHelper.addListener( XGridDataListener::static_type(), i_listener ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::removeGridDataListener( const Reference< grid::XGridDataListener >& i_listener ) throw (RuntimeException) { rBHelper.removeListener( XGridDataListener::static_type(), i_listener ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DefaultGridDataModel::disposing() { ::com::sun::star::lang::EventObject aEvent; aEvent.Source.set( *this ); rBHelper.aLC.disposeAndClear( aEvent ); ::osl::MutexGuard aGuard( m_aMutex ); GridData aEmptyData; m_aData.swap( aEmptyData ); ::std::vector< Any > aEmptyRowHeaders; m_aRowHeaders.swap( aEmptyRowHeaders ); m_nColumnCount = 0; } //------------------------------------------------------------------------------------------------------------------ ::rtl::OUString SAL_CALL DefaultGridDataModel::getImplementationName( ) throw (RuntimeException) { static const ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "toolkit.DefaultGridDataModel" ) ); return aImplName; } //------------------------------------------------------------------------------------------------------------------ sal_Bool SAL_CALL DefaultGridDataModel::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) { return ServiceName.equalsAscii( szServiceName_DefaultGridDataModel ); } //------------------------------------------------------------------------------------------------------------------ Sequence< ::rtl::OUString > SAL_CALL DefaultGridDataModel::getSupportedServiceNames( ) throw (RuntimeException) { static const ::rtl::OUString aServiceName( ::rtl::OUString::createFromAscii( szServiceName_DefaultGridDataModel ) ); static const Sequence< ::rtl::OUString > aSeq( &aServiceName, 1 ); return aSeq; } //------------------------------------------------------------------------------------------------------------------ Reference< XCloneable > SAL_CALL DefaultGridDataModel::createClone( ) throw (RuntimeException) { return new DefaultGridDataModel( *this ); } //...................................................................................................................... } // namespace toolkit //...................................................................................................................... Reference< XInterface > SAL_CALL DefaultGridDataModel_CreateInstance( const Reference< XMultiServiceFactory >& ) { return Reference < XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::DefaultGridDataModel() ); }