summaryrefslogtreecommitdiff
path: root/toolkit/source/controls
diff options
context:
space:
mode:
authorFrank Schoenheit [fs] <frank.schoenheit@oracle.com>2011-01-18 17:30:17 +0100
committerFrank Schoenheit [fs] <frank.schoenheit@oracle.com>2011-01-18 17:30:17 +0100
commitde9dba9275aff2863978f7f665685d54ef82b0ad (patch)
treecce3981b6d9bad32543195b0222a91d9ce30ed31 /toolkit/source/controls
parent961e924dbc7ebd1cea9927134524a443a7666240 (diff)
gridsort: introduce XSortableGridDataModel::removeColumnSort
Diffstat (limited to 'toolkit/source/controls')
-rwxr-xr-xtoolkit/source/controls/grid/sortablegriddatamodel.cxx440
-rwxr-xr-xtoolkit/source/controls/grid/sortablegriddatamodel.hxx68
2 files changed, 479 insertions, 29 deletions
diff --git a/toolkit/source/controls/grid/sortablegriddatamodel.cxx b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
index 4b525dbc925a..d69f3d6187a5 100755
--- a/toolkit/source/controls/grid/sortablegriddatamodel.cxx
+++ b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
@@ -27,18 +27,22 @@
#include "precompiled_toolkit.hxx"
#include "sortablegriddatamodel.hxx"
-#include "initguard.hxx"
#include "toolkit/helper/servicenames.hxx"
/** === begin UNO includes === **/
#include <com/sun/star/i18n/XCollator.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
/** === end UNO includes === **/
#include <comphelper/anycompare.hxx>
+#include <cppuhelper/typeprovider.hxx>
#include <tools/diagnose_ex.h>
+#include <tools/debug.hxx>
#include <vcl/svapp.hxx>
+#include <set>
+
//......................................................................................................................
namespace toolkit
{
@@ -66,38 +70,104 @@ namespace toolkit
using ::com::sun::star::i18n::XCollator;
using ::com::sun::star::lang::IllegalArgumentException;
using ::com::sun::star::lang::XMultiServiceFactory;
+ using ::com::sun::star::awt::grid::GridDataEvent;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::ucb::AlreadyInitializedException;
/** === end UNO using === **/
- typedef InitGuard< SortableGridDataModel > MethodGuard;
+#ifdef DBG_UTIL
+ const char* SortableGridDataModel_checkInvariants( const void* _pInstance )
+ {
+ return static_cast< const SortableGridDataModel* >( _pInstance )->checkInvariants();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ const char* SortableGridDataModel::checkInvariants() const
+ {
+ if ( m_publicToPrivateRowIndex.size() != m_privateToPublicRowIndex.size() )
+ return "inconsistent index maps";
+
+ if ( m_delegator.is() )
+ {
+ if ( m_publicToPrivateRowIndex.size() != size_t( m_delegator->getRowCount() ) )
+ return "wrong cached row count";
+ }
+ else
+ {
+ if ( !m_publicToPrivateRowIndex.empty() )
+ return "disposed or not initialized, but having a non-empty map";
+ }
+
+ for ( size_t publicIndex=0; publicIndex<m_publicToPrivateRowIndex.size(); ++publicIndex )
+ {
+ ::sal_Int32 const privateIndex = m_publicToPrivateRowIndex[ publicIndex ];
+ if ( ( privateIndex < 0 ) || ( size_t( privateIndex ) >= m_privateToPublicRowIndex.size() ) )
+ return "invalid cached private index";
+
+ if ( m_privateToPublicRowIndex[ privateIndex ] != sal_Int32( publicIndex ) )
+ return "index map traversal not commutavive";
+ }
+
+ if ( impl_isSorted_nothrow() && m_publicToPrivateRowIndex.empty() )
+ return "sorted, but no row index translation tables";
+
+ if ( !impl_isSorted_nothrow() && !m_publicToPrivateRowIndex.empty() )
+ return "unsorted, but have index translation tables";
+
+ return NULL;
+ }
+#endif
+
+#define DBG_CHECK_ME() \
+ DBG_CHKTHIS( SortableGridDataModel, SortableGridDataModel_checkInvariants )
+
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
+ {
+ template< class STLCONTAINER >
+ static void lcl_clear( STLCONTAINER& i_container )
+ {
+ STLCONTAINER empty;
+ empty.swap( i_container );
+ }
+ }
//==================================================================================================================
//= SortableGridDataModel
//==================================================================================================================
+ DBG_NAME( SortableGridDataModel )
//------------------------------------------------------------------------------------------------------------------
SortableGridDataModel::SortableGridDataModel( Reference< XMultiServiceFactory > const & i_factory )
:SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
,m_context( i_factory )
,m_isInitialized( false )
,m_delegator()
,m_collator()
,m_currentSortColumn( -1 )
,m_sortAscending( true )
- ,m_rowIndexTranslation()
+ ,m_publicToPrivateRowIndex()
+ ,m_privateToPublicRowIndex()
{
+ DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
}
//------------------------------------------------------------------------------------------------------------------
SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
:cppu::BaseMutex()
,SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
,m_context( i_copySource.m_context )
,m_collator( i_copySource.m_collator )
,m_isInitialized( true )
,m_delegator()
,m_currentSortColumn( i_copySource.m_currentSortColumn )
,m_sortAscending( i_copySource.m_sortAscending )
- ,m_rowIndexTranslation( i_copySource.m_rowIndexTranslation )
+ ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
+ ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
{
+ DBG_CTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
+
ENSURE_OR_THROW( i_copySource.m_delegator.is(),
"not expected to be called for a disposed copy source!" );
m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
@@ -111,6 +181,43 @@ namespace toolkit
acquire();
dispose();
}
+
+ DBG_DTOR( SortableGridDataModel, SortableGridDataModel_checkInvariants );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType ) throw (RuntimeException)
+ {
+ Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
+ if ( !aReturn.hasValue() )
+ aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
+ return aReturn;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::acquire( ) throw ()
+ {
+ SortableGridDataModel_Base::acquire();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::release( ) throw ()
+ {
+ SortableGridDataModel_Base::release();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( ) throw (RuntimeException)
+ {
+ return SortableGridDataModel_Base::getTypes();
+ // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( ) throw (RuntimeException)
+ {
+ static ::cppu::OImplementationId aId;
+ return aId.getImplementationId();
}
//------------------------------------------------------------------------------------------------------------------
@@ -128,6 +235,10 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments ) throw (Exception, RuntimeException)
{
::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ if ( m_delegator.is() )
+ throw AlreadyInitializedException( ::rtl::OUString(), *this );
Reference< XMutableGridDataModel > xDelegator;
Reference< XCollator > xCollator;
@@ -148,13 +259,211 @@ namespace toolkit
if ( !xDelegator.is() )
throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
- // TODO: add as listener to the delegator model, so we're able to multiplex the events it will notify
-
m_delegator = xDelegator;
+ m_collator = xCollator;
+
+ m_delegator->addGridDataListener( this );
+
m_isInitialized = true;
}
//------------------------------------------------------------------------------------------------------------------
+ GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
+ {
+ GridDataEvent aEvent( i_originalEvent );
+ aEvent.Source = *const_cast< SortableGridDataModel* >( this );
+ aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
+ aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
+ return aEvent;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
+ GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
+ {
+ ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( XGridDataListener::static_type() );
+ if ( pListeners == NULL )
+ return;
+
+ i_instanceLock.clear();
+ pListeners->notifyEach( i_listenerMethod, i_publicEvent );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event ) throw (RuntimeException)
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ // if the data is not sorted, broadcast the event unchanged
+ if ( !impl_isSorted_nothrow() )
+ {
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
+ return;
+ }
+
+ bool needReIndex = false;
+ if ( i_event.FirstRow > i_event.LastRow )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsInserted: invalid event - invalid row indexes!" );
+ needReIndex = true;
+ }
+ else if ( size_t( i_event.FirstRow ) > m_privateToPublicRowIndex.size() )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsInserted: invalid event - too large row index!" );
+ needReIndex = true;
+ }
+
+ if ( needReIndex )
+ {
+ impl_rebuildIndexesAndNotify( aGuard );
+ return;
+ }
+
+ // we do not insert the new rows into the sort order - if somebody adds rows while we're sorted, s/he has
+ // to resort. Instead, we simply append the rows, no matter where they were inserted in the delegator data
+ // model.
+ sal_Int32 const nPublicFirstRow = sal_Int32( m_privateToPublicRowIndex.size() );
+ sal_Int32 nPublicLastRow = nPublicFirstRow;
+ for ( sal_Int32 newRow = i_event.FirstRow; newRow <= i_event.LastRow; ++newRow, ++nPublicLastRow )
+ {
+ m_privateToPublicRowIndex.push_back( nPublicLastRow );
+ m_publicToPrivateRowIndex.push_back( nPublicLastRow );
+ }
+
+ // broadcast the event
+ GridDataEvent const aEvent( *this, -1, -1, nPublicFirstRow, nPublicLastRow );
+ impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
+ {
+ void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
+ {
+ for ( ::std::vector< ::sal_Int32 >::iterator loop = io_indexMap.begin();
+ loop != io_indexMap.end();
+ ++loop
+ )
+ {
+ if ( *loop >= i_threshold )
+ --*loop;
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
+ {
+ OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
+
+ // clear the indexes
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+
+ // broadcast an artificial event, saying that all rows have been removed
+ GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
+ impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
+ i_instanceLock.reset();
+
+ // rebuild the index
+ impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending );
+
+ // broadcast an artificial event, saying that n rows have been added
+ GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
+ impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event ) throw (RuntimeException)
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ // if the data is not sorted, broadcast the event unchanged
+ if ( !impl_isSorted_nothrow() )
+ {
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ return;
+ }
+
+ // if all rows have been removed, also simply multiplex to own listeners
+ if ( i_event.FirstRow < 0 )
+ {
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+ GridDataEvent aEvent( i_event );
+ aEvent.Source = *this;
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ return;
+ }
+
+ bool needReIndex = false;
+ if ( i_event.FirstRow != i_event.LastRow )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
+ needReIndex = true;
+ }
+ else if ( size_t( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
+ needReIndex = true;
+ }
+
+ if ( needReIndex )
+ {
+ impl_rebuildIndexesAndNotify( aGuard );
+ return;
+ }
+
+ // build public event version
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+
+ // remove the entries from the index maps
+ sal_Int32 const privateIndex = i_event.FirstRow;
+ sal_Int32 const publicIndex = aEvent.FirstRow;
+
+ m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
+ m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
+
+ // adjust remaining entries in the index maps
+ lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
+ lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
+
+ // broadcast the event
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event ) throw (RuntimeException)
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event ) throw (RuntimeException)
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::disposing( const EventObject& i_event ) throw (RuntimeException)
+ {
+ // not interested in
+ OSL_UNUSED( i_event );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
namespace
{
class CellDataLessComparison : public ::std::binary_function< sal_Int32, sal_Int32, bool >
@@ -199,7 +508,7 @@ namespace toolkit
void SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, sal_Bool const i_sortAscending )
{
::sal_Int32 const rowCount( getRowCount() );
- ::std::vector< ::sal_Int32 > aIndexTranslation( rowCount );
+ ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
try
{
@@ -209,7 +518,7 @@ namespace toolkit
for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
{
aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
- aIndexTranslation[ rowIndex ] = rowIndex;
+ aPublicToPrivate[ rowIndex ] = rowIndex;
// determine the data types we assume for the complete column
if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
@@ -222,7 +531,7 @@ namespace toolkit
// then sort
CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
- ::std::sort( aIndexTranslation.begin(), aIndexTranslation.end(), aComparator );
+ ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
}
catch( const Exception& )
{
@@ -230,13 +539,20 @@ namespace toolkit
return;
}
- m_rowIndexTranslation.swap( aIndexTranslation );
+ // also build the "private to public" mapping
+ ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
+ for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
+ aPrivateToPublic[ aPublicToPrivate[i] ] = i;
+
+ m_publicToPrivateRowIndex.swap( aPublicToPrivate );
+ m_privateToPublicRowIndex.swap( aPrivateToPublic );
}
//------------------------------------------------------------------------------------------------------------------
void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, ::sal_Bool i_sortAscending ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
@@ -245,12 +561,39 @@ namespace toolkit
m_currentSortColumn = i_columnIndex;
m_sortAscending = i_sortAscending;
+
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ aGuard
+ );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void SAL_CALL SortableGridDataModel::removeColumnSort( ) throw (RuntimeException)
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+
+ m_currentSortColumn = -1;
+ m_sortAscending = sal_True;
+
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ aGuard
+ );
}
//------------------------------------------------------------------------------------------------------------------
Pair< ::sal_Int32, ::sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( ) throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
return Pair< ::sal_Int32, ::sal_Bool >( m_currentSortColumn, m_sortAscending );
}
@@ -258,6 +601,8 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data ) throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
m_delegator->addRow( i_heading, i_data );
}
@@ -265,6 +610,8 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data ) throw (IllegalArgumentException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
m_delegator->addRows( i_headings, i_data );
}
@@ -272,7 +619,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->removeRow( rowIndex );
}
@@ -280,6 +629,8 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::removeAllRows( ) throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
m_delegator->removeAllRows();
}
@@ -287,7 +638,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->updateCellData( i_columnIndex, rowIndex, i_value );
}
@@ -295,7 +648,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values ) throw (IndexOutOfBoundsException, IllegalArgumentException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
}
@@ -303,7 +658,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::setRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->setRowHeading( rowIndex, i_heading );
}
@@ -311,7 +668,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
}
@@ -319,7 +678,9 @@ namespace toolkit
void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
m_delegator->updateRowToolTip( rowIndex, i_value );
}
@@ -339,6 +700,8 @@ namespace toolkit
::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount() throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
return m_delegator->getRowCount();
}
@@ -346,6 +709,8 @@ namespace toolkit
::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount() throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
return m_delegator->getColumnCount();
}
@@ -353,7 +718,9 @@ namespace toolkit
Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
return m_delegator->getCellData( i_columnIndex, rowIndex );
}
@@ -361,7 +728,9 @@ namespace toolkit
Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
return m_delegator->getCellToolTip( i_columnIndex, rowIndex );
}
@@ -369,7 +738,9 @@ namespace toolkit
Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
- ::sal_Int32 const rowIndex = impl_translateRowIndex_throw( i_rowIndex );
+ DBG_CHECK_ME();
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
return m_delegator->getRowHeading( rowIndex );
}
@@ -379,6 +750,7 @@ namespace toolkit
m_currentSortColumn = -1;
Reference< XComponent > const delegatorComponent( m_delegator.get() );
+ m_delegator->removeGridDataListener( this );
m_delegator.clear();
delegatorComponent->dispose();
@@ -387,14 +759,16 @@ namespace toolkit
if ( collatorComponent.is() )
collatorComponent->dispose();
- ::std::vector< ::sal_Int32 > aEmpty;
- m_rowIndexTranslation.swap( aEmpty );
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
}
//------------------------------------------------------------------------------------------------------------------
Reference< XCloneable > SAL_CALL SortableGridDataModel::createClone( ) throw (RuntimeException)
{
MethodGuard aGuard( *this, rBHelper );
+ DBG_CHECK_ME();
+
return new SortableGridDataModel( *this );
}
@@ -423,7 +797,7 @@ namespace toolkit
}
//------------------------------------------------------------------------------------------------------------------
- ::sal_Int32 SortableGridDataModel::impl_translateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
+ ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
{
if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SortableGridDataModel* >( this ) );
@@ -432,12 +806,28 @@ namespace toolkit
// no need to translate anything
return i_publicRowIndex;
- ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_rowIndexTranslation.size(),
- "SortableGridDataModel::impl_translateRowIndex_throw: inconsistency!", i_publicRowIndex );
+ ENSURE_OR_RETURN( size_t( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
+ "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
// obviously the translation table contains too few elements - it should have exactly |getRowCount()|
// elements
- return m_rowIndexTranslation[ i_publicRowIndex ];
+ return m_publicToPrivateRowIndex[ i_publicRowIndex ];
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
+ {
+ if ( !impl_isSorted_nothrow() )
+ // no need to translate anything
+ return i_privateRowIndex;
+
+ if ( i_privateRowIndex < 0 )
+ return i_privateRowIndex;
+
+ ENSURE_OR_RETURN( size_t( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
+ "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
+
+ return m_privateToPublicRowIndex[ i_privateRowIndex ];
}
//......................................................................................................................
diff --git a/toolkit/source/controls/grid/sortablegriddatamodel.hxx b/toolkit/source/controls/grid/sortablegriddatamodel.hxx
index 64dad34af2bf..26f0e63f9762 100755
--- a/toolkit/source/controls/grid/sortablegriddatamodel.hxx
+++ b/toolkit/source/controls/grid/sortablegriddatamodel.hxx
@@ -27,22 +27,29 @@
#ifndef TOOLKIT_SORTABLEGRIDDATAMODEL_HXX
#define TOOLKIT_SORTABLEGRIDDATAMODEL_HXX
+#include "initguard.hxx"
+
/** === begin UNO includes === **/
#include <com/sun/star/awt/grid/XSortableMutableGridDataModel.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/i18n/XCollator.hpp>
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
/** === end UNO includes === **/
#include <comphelper/componentcontext.hxx>
#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/compbase3.hxx>
+#include <cppuhelper/implbase1.hxx>
//......................................................................................................................
namespace toolkit
{
//......................................................................................................................
+ class SortableGridDataModel;
+ typedef InitGuard< SortableGridDataModel > MethodGuard;
+
//==================================================================================================================
//= SortableGridDataModel
//==================================================================================================================
@@ -50,22 +57,29 @@ namespace toolkit
, ::com::sun::star::lang::XServiceInfo
, ::com::sun::star::lang::XInitialization
> SortableGridDataModel_Base;
+ typedef ::cppu::ImplHelper1 < ::com::sun::star::awt::grid::XGridDataListener
+ > SortableGridDataModel_PrivateBase;
class SortableGridDataModel :public ::cppu::BaseMutex
,public SortableGridDataModel_Base
+ ,public SortableGridDataModel_PrivateBase
{
public:
SortableGridDataModel( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > const & i_factory );
SortableGridDataModel( SortableGridDataModel const & i_copySource );
- public:
bool isInitialized() const { return m_isInitialized; }
+#ifdef DBG_UTIL
+ const char* checkInvariants() const;
+#endif
+
protected:
~SortableGridDataModel();
public:
- // XSortableGridData
+ // XSortableGridDataModel
virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, ::sal_Bool SortAscending ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeColumnSort( ) throw (::com::sun::star::uno::RuntimeException);
virtual ::com::sun::star::beans::Pair< ::sal_Int32, ::sal_Bool > SAL_CALL getCurrentSortOrder( ) throw (::com::sun::star::uno::RuntimeException);
// XMutableGridDataModel
@@ -102,12 +116,34 @@ namespace toolkit
// XInitialization
virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
+ // XGridDataListener
+ virtual void SAL_CALL rowsInserted( const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL rowsRemoved( const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL dataChanged( const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL rowHeadingChanged( const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& i_event ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XInterface
+ virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL acquire( ) throw ();
+ virtual void SAL_CALL release( ) throw ();
+
+ // XTypeProvider
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getImplementationId( ) throw (::com::sun::star::uno::RuntimeException);
+
private:
/** translates the given public index into one to be passed to our delegator
@throws ::com::sun::star::lang::IndexOutOfBoundsException
if the given index does not denote a valid row
*/
- ::sal_Int32 impl_translateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const;
+ ::sal_Int32 impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const;
+
+ /** translates the given private row index to a public one
+ */
+ ::sal_Int32 impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const;
inline bool impl_isSorted_nothrow() const
{
@@ -121,6 +157,29 @@ namespace toolkit
*/
void impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, sal_Bool const i_sortAscending );
+ /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
+ clients.
+ */
+ ::com::sun::star::awt::grid::GridDataEvent
+ impl_createPublicEvent( ::com::sun::star::awt::grid::GridDataEvent const & i_originalEvent ) const;
+
+ /** broadcasts the given event to our registered XGridDataListeners
+ */
+ void impl_broadcast(
+ void ( SAL_CALL ::com::sun::star::awt::grid::XGridDataListener::*i_listenerMethod )( const ::com::sun::star::awt::grid::GridDataEvent & ),
+ ::com::sun::star::awt::grid::GridDataEvent const & i_publicEvent,
+ MethodGuard& i_instanceLock
+ );
+
+ /** rebuilds our indexes, notifying row removal and row addition events
+
+ First, a rowsRemoved event is notified to our registered listeners. Then, the index translation tables are
+ rebuilt, and a rowsInserted event is notified.
+
+ Only to be called when we're sorted.
+ */
+ void impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock );
+
private:
::comphelper::ComponentContext m_context;
bool m_isInitialized;
@@ -128,7 +187,8 @@ namespace toolkit
::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCollator > m_collator;
::sal_Int32 m_currentSortColumn;
::sal_Bool m_sortAscending;
- ::std::vector< ::sal_Int32 > m_rowIndexTranslation;
+ ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
+ ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
};
//......................................................................................................................