summaryrefslogtreecommitdiffstats
path: root/toolkit/source/controls/grid
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /toolkit/source/controls/grid
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/source/controls/grid')
-rw-r--r--toolkit/source/controls/grid/defaultgridcolumnmodel.cxx389
-rw-r--r--toolkit/source/controls/grid/defaultgriddatamodel.cxx505
-rw-r--r--toolkit/source/controls/grid/gridcolumn.cxx300
-rw-r--r--toolkit/source/controls/grid/gridcolumn.hxx128
-rw-r--r--toolkit/source/controls/grid/gridcontrol.cxx460
-rw-r--r--toolkit/source/controls/grid/gridcontrol.hxx142
-rw-r--r--toolkit/source/controls/grid/grideventforwarder.cxx128
-rw-r--r--toolkit/source/controls/grid/grideventforwarder.hxx77
-rw-r--r--toolkit/source/controls/grid/sortablegriddatamodel.cxx928
9 files changed, 3057 insertions, 0 deletions
diff --git a/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx b/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx
new file mode 100644
index 000000000..ad17d15ea
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "gridcolumn.hxx"
+
+#include <com/sun/star/awt/grid/XGridColumnModel.hpp>
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/componentguard.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vector>
+
+using namespace css::awt;
+using namespace css::awt::grid;
+using namespace css::container;
+using namespace css::lang;
+using namespace css::uno;
+using namespace toolkit;
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XGridColumnModel
+ , css::lang::XServiceInfo
+ > DefaultGridColumnModel_Base;
+
+class DefaultGridColumnModel :public ::cppu::BaseMutex
+ ,public DefaultGridColumnModel_Base
+{
+public:
+ DefaultGridColumnModel();
+ DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource );
+
+ // XGridColumnModel
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Reference< css::awt::grid::XGridColumn > SAL_CALL createColumn( ) override;
+ virtual ::sal_Int32 SAL_CALL addColumn(const css::uno::Reference< css::awt::grid::XGridColumn > & column) override;
+ virtual void SAL_CALL removeColumn( ::sal_Int32 i_columnIndex ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::awt::grid::XGridColumn > > SAL_CALL getColumns() override;
+ virtual css::uno::Reference< css::awt::grid::XGridColumn > SAL_CALL getColumn(::sal_Int32 index) override;
+ virtual void SAL_CALL setDefaultColumns(sal_Int32 rowElements) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+private:
+ typedef ::std::vector< css::uno::Reference< css::awt::grid::XGridColumn > > Columns;
+
+ ::comphelper::OInterfaceContainerHelper3<XContainerListener> m_aContainerListeners;
+ Columns m_aColumns;
+};
+
+ DefaultGridColumnModel::DefaultGridColumnModel()
+ :DefaultGridColumnModel_Base( m_aMutex )
+ ,m_aContainerListeners( m_aMutex )
+ {
+ }
+
+ DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
+ :cppu::BaseMutex()
+ ,DefaultGridColumnModel_Base( m_aMutex )
+ ,m_aContainerListeners( m_aMutex )
+ {
+ Columns aColumns;
+ aColumns.reserve( i_copySource.m_aColumns.size() );
+ try
+ {
+ for ( Columns::const_iterator col = i_copySource.m_aColumns.begin();
+ col != i_copySource.m_aColumns.end();
+ ++col
+ )
+ {
+ Reference< css::util::XCloneable > const xCloneable( *col, UNO_QUERY_THROW );
+ Reference< XGridColumn > const xClone( xCloneable->createClone(), UNO_QUERY_THROW );
+
+ GridColumn* const pGridColumn = comphelper::getFromUnoTunnel<GridColumn>( xClone );
+ if ( pGridColumn == nullptr )
+ throw RuntimeException( "invalid clone source implementation", *this );
+ // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
+ // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
+ // is borked.
+ pGridColumn->setIndex( col - i_copySource.m_aColumns.begin() );
+
+ aColumns.push_back( xClone );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( aColumns.size() == i_copySource.m_aColumns.size() )
+ m_aColumns.swap( aColumns );
+ }
+
+ ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount()
+ {
+ return m_aColumns.size();
+ }
+
+
+ Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn( )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return new GridColumn();
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ GridColumn* const pGridColumn = comphelper::getFromUnoTunnel<GridColumn>( i_column );
+ if ( pGridColumn == nullptr )
+ throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
+
+ m_aColumns.push_back( i_column );
+ sal_Int32 index = m_aColumns.size() - 1;
+ pGridColumn->setIndex( index );
+
+ // fire insertion notifications
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= index;
+ aEvent.Element <<= i_column;
+
+ aGuard.clear();
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+
+ return index;
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_columnIndex < 0 ) || ( o3tl::make_unsigned( i_columnIndex ) >= m_aColumns.size() ) )
+ throw css::lang::IndexOutOfBoundsException( OUString(), *this );
+
+ Columns::iterator const pos = m_aColumns.begin() + i_columnIndex;
+ Reference< XGridColumn > const xColumn( *pos );
+ m_aColumns.erase( pos );
+
+ // update indexes of all subsequent columns
+ sal_Int32 columnIndex( i_columnIndex );
+ for ( Columns::iterator updatePos = m_aColumns.begin() + columnIndex;
+ updatePos != m_aColumns.end();
+ ++updatePos, ++columnIndex
+ )
+ {
+ GridColumn* pColumnImpl = comphelper::getFromUnoTunnel<GridColumn>( *updatePos );
+ if ( !pColumnImpl )
+ {
+ SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
+ continue;
+ }
+
+ pColumnImpl->setIndex( columnIndex );
+ }
+
+ // fire removal notifications
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= i_columnIndex;
+ aEvent.Element <<= xColumn;
+
+ aGuard.clear();
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
+
+ // dispose the removed column
+ try
+ {
+ xColumn->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns()
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return ::comphelper::containerToSequence( m_aColumns );
+ }
+
+
+ Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index)
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( index >=0 && o3tl::make_unsigned(index) < m_aColumns.size())
+ return m_aColumns[index];
+
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements)
+ {
+ ::std::vector< ContainerEvent > aRemovedColumns;
+ ::std::vector< ContainerEvent > aInsertedColumns;
+
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ // remove existing columns
+ while ( !m_aColumns.empty() )
+ {
+ const size_t lastColIndex = m_aColumns.size() - 1;
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= sal_Int32( lastColIndex );
+ aEvent.Element <<= m_aColumns[ lastColIndex ];
+ aRemovedColumns.push_back( aEvent );
+
+ m_aColumns.erase( m_aColumns.begin() + lastColIndex );
+ }
+
+ // add new columns
+ for ( sal_Int32 i=0; i<rowElements; ++i )
+ {
+ ::rtl::Reference< GridColumn > const pGridColumn = new GridColumn();
+ Reference< XGridColumn > const xColumn( pGridColumn );
+ OUString colTitle = "Column " + OUString::number( i + 1 );
+ pGridColumn->setTitle( colTitle );
+ pGridColumn->setColumnWidth( 80 /* APPFONT */ );
+ pGridColumn->setFlexibility( 1 );
+ pGridColumn->setResizeable( true );
+ pGridColumn->setDataColumnIndex( i );
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= i;
+ aEvent.Element <<= xColumn;
+ aInsertedColumns.push_back( aEvent );
+
+ m_aColumns.push_back( xColumn );
+ pGridColumn->setIndex( i );
+ }
+ }
+
+ // fire removal notifications
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, rEvent );
+ }
+
+ // fire insertion notifications
+ for (const auto& rEvent : aInsertedColumns)
+ {
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, rEvent );
+ }
+
+ // dispose removed columns
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ try
+ {
+ const Reference< XComponent > xColComp( rEvent.Element, UNO_QUERY_THROW );
+ xColComp->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+ }
+
+
+ OUString SAL_CALL DefaultGridColumnModel::getImplementationName( )
+ {
+ return "stardiv.Toolkit.DefaultGridColumnModel";
+ }
+
+ sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ Sequence< OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.DefaultGridColumnModel" };
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_aContainerListeners.addInterface( i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_aContainerListeners.removeInterface( i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::disposing()
+ {
+ DefaultGridColumnModel_Base::disposing();
+
+ EventObject aEvent( *this );
+ m_aContainerListeners.disposeAndClear( aEvent );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // remove, dispose and clear columns
+ while ( !m_aColumns.empty() )
+ {
+ try
+ {
+ const Reference< XComponent > xColComponent( m_aColumns[ 0 ], UNO_QUERY_THROW );
+ xColComponent->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ m_aColumns.erase( m_aColumns.begin() );
+ }
+
+ Columns().swap(m_aColumns);
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL DefaultGridColumnModel::createClone( )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return new DefaultGridColumnModel( *this );
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_DefaultGridColumnModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new DefaultGridColumnModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/defaultgriddatamodel.cxx b/toolkit/source/controls/grid/defaultgriddatamodel.cxx
new file mode 100644
index 000000000..2e5f4e305
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgriddatamodel.cxx
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/componentguard.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+
+#include <algorithm>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::grid;
+using namespace ::com::sun::star::lang;
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper < XMutableGridDataModel
+ , XServiceInfo
+ > DefaultGridDataModel_Base;
+
+class DefaultGridDataModel :public ::cppu::BaseMutex
+ ,public DefaultGridDataModel_Base
+{
+public:
+ DefaultGridDataModel();
+ DefaultGridDataModel( DefaultGridDataModel const & i_copySource );
+
+ // XMutableGridDataModel
+ virtual void SAL_CALL addRow( const Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
+ virtual void SAL_CALL removeAllRows( ) override;
+ virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
+ virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
+ virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+ virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+
+ // XGridDataModel
+ virtual ::sal_Int32 SAL_CALL getRowCount() override;
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 Row ) override;
+ virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 Row ) override;
+ virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+private:
+ typedef ::std::pair< Any, Any > CellData;
+ typedef ::std::vector< CellData > RowData;
+ typedef ::std::vector< RowData > GridData;
+
+ void broadcast(
+ GridDataEvent const & i_event,
+ void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( css::awt::grid::GridDataEvent const & ),
+ ::comphelper::ComponentGuard & i_instanceLock
+ );
+
+ void impl_insertRow( sal_Int32 const i_position, Any const & i_heading, Sequence< Any > const & i_rowData, sal_Int32 const i_assumedColCount = -1 );
+
+ ::sal_Int32 impl_getRowCount_nolck() const { return sal_Int32( m_aData.size() ); }
+
+ CellData const & impl_getCellData_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex ) const;
+ CellData& impl_getCellDataAccess_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex );
+ RowData& impl_getRowDataAccess_throw( sal_Int32 const i_rowIndex, size_t const i_requiredColumnCount );
+
+ GridData m_aData;
+ ::std::vector< css::uno::Any > m_aRowHeaders;
+ sal_Int32 m_nColumnCount;
+};
+
+ DefaultGridDataModel::DefaultGridDataModel()
+ :DefaultGridDataModel_Base( m_aMutex )
+ ,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 )
+ {
+ }
+
+ void DefaultGridDataModel::broadcast( GridDataEvent const & i_event,
+ void ( SAL_CALL XGridDataListener::*i_listenerMethod )( GridDataEvent const & ), ::comphelper::ComponentGuard & i_instanceLock )
+ {
+ ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( cppu::UnoType<XGridDataListener>::get() );
+ if ( !pListeners )
+ return;
+
+ i_instanceLock.clear();
+ pListeners->notifyEach( i_listenerMethod, i_event );
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getRowCount()
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return impl_getRowCount_nolck();
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getColumnCount()
+ {
+ ::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 ) || ( o3tl::make_unsigned( i_row ) > m_aData.size() )
+ || ( i_column < 0 ) || ( i_column > m_nColumnCount )
+ )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< DefaultGridDataModel* >( this ) );
+
+ RowData const & rRow( m_aData[ i_row ] );
+ if ( o3tl::make_unsigned( 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 <= o3tl::make_unsigned( m_nColumnCount ), "DefaultGridDataModel::impl_getRowDataAccess_throw: invalid column count!" );
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( 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( 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 )
+ {
+ ::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 )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return impl_getCellData_throw( i_column, i_row ).second;
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_row < 0 ) || ( o3tl::make_unsigned( i_row ) >= m_aRowHeaders.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ return m_aRowHeaders[ i_row ];
+ }
+
+
+ Sequence< Any > SAL_CALL DefaultGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
+ {
+ ::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(),
+ [] ( const CellData& rCellData )
+ { return rCellData.first; });
+ 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& rData : i_rowData )
+ {
+ cellData->first = rData;
+ ++cellData;
+ }
+
+ // 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 )
+ {
+ insertRow( getRowCount(), i_heading, i_data );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ insertRows( getRowCount(), i_headings, i_data );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) )
+ throw IndexOutOfBoundsException( 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 )
+ {
+ if ( i_headings.getLength() != i_data.getLength() )
+ throw IllegalArgumentException( OUString(), *this, -1 );
+
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ sal_Int32 const rowCount = i_headings.getLength();
+ if ( rowCount == 0 )
+ return;
+
+ // determine max col count in the new data
+ auto pData = std::max_element(i_data.begin(), i_data.end(),
+ [](const Sequence< Any >& a, const Sequence< Any >& b) { return a.getLength() < b.getLength(); });
+ sal_Int32 maxColCount = pData->getLength();
+
+ if ( maxColCount < m_nColumnCount )
+ maxColCount = m_nColumnCount;
+
+ for ( sal_Int32 row=0; row<rowCount; ++row )
+ {
+ impl_insertRow( i_index + row, i_headings[row], i_data[row], maxColCount );
+ }
+
+ if ( maxColCount > 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 )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( 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( )
+ {
+ ::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 )
+ {
+ ::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 )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ if ( i_columnIndexes.getLength() != i_values.getLength() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ sal_Int32 const columnCount = i_columnIndexes.getLength();
+ if ( columnCount == 0 )
+ return;
+
+ for ( sal_Int32 const columnIndex : i_columnIndexes )
+ {
+ if ( ( columnIndex < 0 ) || ( columnIndex > m_nColumnCount ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+ }
+
+ RowData& rDataRow = m_aData[ i_rowIndex ];
+ for ( sal_Int32 col = 0; col < columnCount; ++col )
+ {
+ sal_Int32 const columnIndex = i_columnIndexes[ col ];
+ if ( o3tl::make_unsigned( columnIndex ) >= rDataRow.size() )
+ rDataRow.resize( columnIndex + 1 );
+
+ rDataRow[ columnIndex ].first = i_values[ col ];
+ }
+
+ auto aPair = ::std::minmax_element( i_columnIndexes.begin(), i_columnIndexes.end() );
+ sal_Int32 const firstAffectedColumn = *aPair.first;
+ sal_Int32 const lastAffectedColumn = *aPair.second;
+ 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 )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aRowHeaders.size() ) )
+ throw IndexOutOfBoundsException( 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 )
+ {
+ ::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 )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ RowData& rRowData = impl_getRowDataAccess_throw( i_rowIndex, m_nColumnCount );
+ for ( auto& rCell : rRowData )
+ rCell.second = i_value;
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::removeGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::disposing()
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source.set( *this );
+ rBHelper.aLC.disposeAndClear( aEvent );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ GridData().swap(m_aData);
+ std::vector<Any>().swap(m_aRowHeaders);
+ m_nColumnCount = 0;
+ }
+
+
+ OUString SAL_CALL DefaultGridDataModel::getImplementationName( )
+ {
+ return "stardiv.Toolkit.DefaultGridDataModel";
+ }
+
+ sal_Bool SAL_CALL DefaultGridDataModel::supportsService( const OUString& ServiceName )
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ Sequence< OUString > SAL_CALL DefaultGridDataModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.DefaultGridDataModel" };
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL DefaultGridDataModel::createClone( )
+ {
+ return new DefaultGridDataModel( *this );
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_DefaultGridDataModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new DefaultGridDataModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcolumn.cxx b/toolkit/source/controls/grid/gridcolumn.cxx
new file mode 100644
index 000000000..11a03e647
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "gridcolumn.hxx"
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace toolkit
+{
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::awt::grid;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::style;
+
+
+ //= DefaultGridColumnModel
+
+
+ GridColumn::GridColumn()
+ :m_nIndex(-1)
+ ,m_nDataColumnIndex(-1)
+ ,m_nColumnWidth(4)
+ ,m_nMaxWidth(0)
+ ,m_nMinWidth(0)
+ ,m_nFlexibility(1)
+ ,m_bResizeable(true)
+ ,m_eHorizontalAlign( HorizontalAlignment_LEFT )
+ {
+ }
+
+
+ GridColumn::GridColumn( GridColumn const & i_copySource )
+ :m_aIdentifier( i_copySource.m_aIdentifier )
+ ,m_nIndex( -1 )
+ ,m_nDataColumnIndex( i_copySource.m_nDataColumnIndex )
+ ,m_nColumnWidth( i_copySource.m_nColumnWidth )
+ ,m_nMaxWidth( i_copySource.m_nMaxWidth )
+ ,m_nMinWidth( i_copySource.m_nMinWidth )
+ ,m_nFlexibility( i_copySource.m_nFlexibility )
+ ,m_bResizeable( i_copySource.m_bResizeable )
+ ,m_sTitle( i_copySource.m_sTitle )
+ ,m_sHelpText( i_copySource.m_sHelpText )
+ ,m_eHorizontalAlign( i_copySource.m_eHorizontalAlign )
+ {
+ }
+
+
+ GridColumn::~GridColumn()
+ {
+ }
+
+
+ void GridColumn::broadcast_changed( char const * const i_asciiAttributeName, const Any& i_oldValue, const Any& i_newValue,
+ std::unique_lock<std::mutex>& i_Guard )
+ {
+ Reference< XInterface > const xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ GridColumnEvent const aEvent(
+ xSource, OUString::createFromAscii( i_asciiAttributeName ),
+ i_oldValue, i_newValue, m_nIndex
+ );
+
+ maGridColumnListeners.notifyEach( i_Guard, &XGridColumnListener::columnChanged, aEvent );
+ }
+
+
+ css::uno::Any SAL_CALL GridColumn::getIdentifier()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_aIdentifier;
+ }
+
+
+ void SAL_CALL GridColumn::setIdentifier(const css::uno::Any & value)
+ {
+ std::unique_lock aGuard( m_aMutex );
+ m_aIdentifier = value;
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getColumnWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nColumnWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setColumnWidth(::sal_Int32 value)
+ {
+ impl_set( m_nColumnWidth, value, "ColumnWidth" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getMaxWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nMaxWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setMaxWidth(::sal_Int32 value)
+ {
+ impl_set( m_nMaxWidth, value, "MaxWidth" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getMinWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nMinWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setMinWidth(::sal_Int32 value)
+ {
+ impl_set( m_nMinWidth, value, "MinWidth" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getTitle()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_sTitle;
+ }
+
+
+ void SAL_CALL GridColumn::setTitle(const OUString & value)
+ {
+ impl_set( m_sTitle, value, "Title" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getHelpText()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_sHelpText;
+ }
+
+
+ void SAL_CALL GridColumn::setHelpText( const OUString & value )
+ {
+ impl_set( m_sHelpText, value, "HelpText" );
+ }
+
+
+ sal_Bool SAL_CALL GridColumn::getResizeable()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_bResizeable;
+ }
+
+
+ void SAL_CALL GridColumn::setResizeable(sal_Bool value)
+ {
+ impl_set( m_bResizeable, bool(value), "Resizeable" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getFlexibility()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nFlexibility;
+ }
+
+
+ void SAL_CALL GridColumn::setFlexibility( ::sal_Int32 i_value )
+ {
+ if ( i_value < 0 )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+ impl_set( m_nFlexibility, i_value, "Flexibility" );
+ }
+
+
+ HorizontalAlignment SAL_CALL GridColumn::getHorizontalAlign()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_eHorizontalAlign;
+ }
+
+
+ void SAL_CALL GridColumn::setHorizontalAlign(HorizontalAlignment align)
+ {
+ impl_set( m_eHorizontalAlign, align, "HorizontalAlign" );
+ }
+
+
+ void SAL_CALL GridColumn::addGridColumnListener( const Reference< XGridColumnListener >& xListener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maGridColumnListeners.addInterface( aGuard, xListener );
+ }
+
+
+ void SAL_CALL GridColumn::removeGridColumnListener( const Reference< XGridColumnListener >& xListener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maGridColumnListeners.removeInterface( aGuard, xListener );
+ }
+
+
+ void GridColumn::disposing(std::unique_lock<std::mutex>&)
+ {
+ m_aIdentifier.clear();
+ m_sTitle.clear();
+ m_sHelpText.clear();
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getIndex()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nIndex;
+ }
+
+
+ void GridColumn::setIndex( sal_Int32 const i_index )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ m_nIndex = i_index;
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getDataColumnIndex()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nDataColumnIndex;
+ }
+
+
+ void SAL_CALL GridColumn::setDataColumnIndex( ::sal_Int32 i_dataColumnIndex )
+ {
+ impl_set( m_nDataColumnIndex, i_dataColumnIndex, "DataColumnIndex" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.GridColumn";
+ }
+
+ sal_Bool SAL_CALL GridColumn::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ css::uno::Sequence< OUString > SAL_CALL GridColumn::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.GridColumn" };
+ }
+
+
+ Reference< XCloneable > SAL_CALL GridColumn::createClone( )
+ {
+ return new GridColumn( *this );
+ }
+
+
+ sal_Int64 SAL_CALL GridColumn::getSomething( const Sequence< sal_Int8 >& i_identifier )
+ {
+ return comphelper::getSomethingImpl(i_identifier, this);
+ }
+
+
+ const Sequence< sal_Int8 > & GridColumn::getUnoTunnelId() noexcept
+ {
+ static const comphelper::UnoIdInit aId;
+ return aId.getSeq();
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_GridColumn_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::GridColumn());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcolumn.hxx b/toolkit/source/controls/grid/gridcolumn.hxx
new file mode 100644
index 000000000..8008c077d
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <comphelper/compbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+
+namespace toolkit
+{
+
+typedef comphelper::WeakComponentImplHelper < css::awt::grid::XGridColumn
+ , css::lang::XServiceInfo
+ , css::lang::XUnoTunnel
+ > GridColumn_Base;
+class GridColumn final : public GridColumn_Base
+{
+public:
+ GridColumn();
+ GridColumn( GridColumn const & i_copySource );
+ virtual ~GridColumn() override;
+
+ // css::awt::grid::XGridColumn
+ virtual css::uno::Any SAL_CALL getIdentifier() override;
+ virtual void SAL_CALL setIdentifier(const css::uno::Any & value) override;
+ virtual ::sal_Int32 SAL_CALL getColumnWidth() override;
+ virtual void SAL_CALL setColumnWidth(::sal_Int32 the_value) override;
+ virtual ::sal_Int32 SAL_CALL getMaxWidth() override;
+ virtual void SAL_CALL setMaxWidth(::sal_Int32 the_value) override;
+ virtual ::sal_Int32 SAL_CALL getMinWidth() override;
+ virtual void SAL_CALL setMinWidth(::sal_Int32 the_value) override;
+ virtual sal_Bool SAL_CALL getResizeable() override;
+ virtual void SAL_CALL setResizeable(sal_Bool the_value) override;
+ virtual ::sal_Int32 SAL_CALL getFlexibility() override;
+ virtual void SAL_CALL setFlexibility( ::sal_Int32 _flexibility ) override;
+ virtual OUString SAL_CALL getTitle() override;
+ virtual void SAL_CALL setTitle(const OUString & value) override;
+ virtual OUString SAL_CALL getHelpText() override;
+ virtual void SAL_CALL setHelpText(const OUString & value) override;
+ virtual ::sal_Int32 SAL_CALL getIndex() override;
+ virtual ::sal_Int32 SAL_CALL getDataColumnIndex() override;
+ virtual void SAL_CALL setDataColumnIndex( ::sal_Int32 i_dataColumnIndex ) override;
+ virtual css::style::HorizontalAlignment SAL_CALL getHorizontalAlign() override;
+ virtual void SAL_CALL setHorizontalAlign(css::style::HorizontalAlignment align) override;
+ virtual void SAL_CALL addGridColumnListener( const css::uno::Reference< css::awt::grid::XGridColumnListener >& xListener ) override;
+ virtual void SAL_CALL removeGridColumnListener( const css::uno::Reference< css::awt::grid::XGridColumnListener >& xListener ) override;
+
+ // OComponentHelper
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
+
+ // XCloneable (base of XGridColumn)
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XUnoTunnel and friends
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& i_identifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId() noexcept;
+
+ // attribute access
+ void setIndex( sal_Int32 const i_index );
+
+private:
+ void broadcast_changed(
+ char const * const i_asciiAttributeName,
+ const css::uno::Any& i_oldValue,
+ const css::uno::Any& i_newValue,
+ std::unique_lock<std::mutex>& i_Guard
+ );
+
+ template< class TYPE >
+ void impl_set( TYPE & io_attribute, TYPE const & i_newValue, char const * i_attributeName )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ if (m_bDisposed)
+ throw css::lang::DisposedException( OUString(), static_cast<cppu::OWeakObject*>(this) );
+ if ( io_attribute == i_newValue )
+ return;
+
+ TYPE const aOldValue( io_attribute );
+ io_attribute = i_newValue;
+ broadcast_changed( i_attributeName, css::uno::Any( aOldValue ), css::uno::Any( io_attribute ), aGuard );
+ }
+
+ css::uno::Any m_aIdentifier;
+ sal_Int32 m_nIndex;
+ sal_Int32 m_nDataColumnIndex;
+ sal_Int32 m_nColumnWidth;
+ sal_Int32 m_nMaxWidth;
+ sal_Int32 m_nMinWidth;
+ sal_Int32 m_nFlexibility;
+ bool m_bResizeable;
+ OUString m_sTitle;
+ OUString m_sHelpText;
+ css::style::HorizontalAlignment m_eHorizontalAlign;
+ comphelper::OInterfaceContainerHelper4<css::awt::grid::XGridColumnListener> maGridColumnListeners;
+};
+
+}
+
+#endif // INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcontrol.cxx b/toolkit/source/controls/grid/gridcontrol.cxx
new file mode 100644
index 000000000..4bf996c8e
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcontrol.cxx
@@ -0,0 +1,460 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+
+#include "gridcontrol.hxx"
+#include "grideventforwarder.hxx"
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridDataModel.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
+#include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
+#include <com/sun/star/awt/grid/DefaultGridDataModel.hpp>
+#include <com/sun/star/awt/grid/SortableGridDataModel.hpp>
+#include <com/sun/star/awt/grid/DefaultGridColumnModel.hpp>
+#include <toolkit/helper/property.hxx>
+#include <tools/diagnose_ex.h>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <memory>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::grid;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::util;
+
+namespace toolkit {
+
+namespace
+{
+ Reference< XGridDataModel > lcl_getDefaultDataModel_throw( const Reference<XComponentContext> & i_context )
+ {
+ Reference< XMutableGridDataModel > const xDelegatorModel( DefaultGridDataModel::create( i_context ), UNO_SET_THROW );
+ Reference< XGridDataModel > const xDataModel( SortableGridDataModel::create( i_context, xDelegatorModel ), UNO_QUERY_THROW );
+ return xDataModel;
+ }
+
+ Reference< XGridColumnModel > lcl_getDefaultColumnModel_throw( const Reference<XComponentContext> & i_context )
+ {
+ Reference< XGridColumnModel > const xColumnModel = DefaultGridColumnModel::create( i_context );
+ return xColumnModel;
+ }
+}
+
+
+UnoGridModel::UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); // resizable
+ ImplRegisterProperty( BASEPROPERTY_HSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_VSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SHOWROWHEADER );
+ ImplRegisterProperty( BASEPROPERTY_ROW_HEADER_WIDTH );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SHOWCOLUMNHEADER );
+ ImplRegisterProperty( BASEPROPERTY_COLUMN_HEADER_HEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_GRID_DATAMODEL, Any( lcl_getDefaultDataModel_throw( m_xContext ) ) );
+ ImplRegisterProperty( BASEPROPERTY_GRID_COLUMNMODEL, Any( lcl_getDefaultColumnModel_throw( m_xContext ) ) );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SELECTIONMODE );
+ ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
+ ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
+ ImplRegisterProperty( BASEPROPERTY_USE_GRID_LINES );
+ ImplRegisterProperty( BASEPROPERTY_GRID_LINE_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_BACKGROUND );
+ ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS );
+ ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
+}
+
+
+UnoGridModel::UnoGridModel( const UnoGridModel& rModel )
+ :UnoControlModel( rModel )
+{
+ osl_atomic_increment( &m_refCount );
+ {
+ Reference< XGridDataModel > xDataModel;
+ // clone the data model
+ const Reference< XFastPropertySet > xCloneSource( &const_cast< UnoGridModel& >( rModel ) );
+ try
+ {
+ const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ), UNO_QUERY_THROW );
+ xDataModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( !xDataModel.is() )
+ xDataModel = lcl_getDefaultDataModel_throw( m_xContext );
+ UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_DATAMODEL, Any( xDataModel ) );
+ // do *not* use setFastPropertyValue here: The UnoControlModel ctor made a simple copy of all property values,
+ // so before this call here, we share our data model with the own of the clone source. setFastPropertyValue,
+ // then, disposes the old data model - which means the data model which in fact belongs to the clone source.
+ // so, call the UnoControlModel's impl-method for setting the value.
+
+ // clone the column model
+ Reference< XGridColumnModel > xColumnModel;
+ try
+ {
+ const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ), UNO_QUERY_THROW );
+ xColumnModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( !xColumnModel.is() )
+ xColumnModel = lcl_getDefaultColumnModel_throw( m_xContext );
+ UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_COLUMNMODEL, Any( xColumnModel ) );
+ // same comment as above: do not use our own setPropertyValue here.
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+
+rtl::Reference<UnoControlModel> UnoGridModel::Clone() const
+{
+ return new UnoGridModel( *this );
+}
+
+
+namespace
+{
+ void lcl_dispose_nothrow( const Any& i_component )
+ {
+ try
+ {
+ const Reference< XComponent > xComponent( i_component, UNO_QUERY_THROW );
+ xComponent->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+}
+
+
+void SAL_CALL UnoGridModel::dispose( )
+{
+ lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ) );
+ lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ) );
+
+ UnoControlModel::dispose();
+}
+
+
+void SAL_CALL UnoGridModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ Any aOldSubModel;
+ if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
+ {
+ aOldSubModel = getFastPropertyValue( nHandle );
+ if ( aOldSubModel == rValue )
+ {
+ OSL_ENSURE( false, "UnoGridModel::setFastPropertyValue_NoBroadcast: setting the same value, again!" );
+ // shouldn't this have been caught by convertFastPropertyValue?
+ aOldSubModel.clear();
+ }
+ }
+
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ if ( aOldSubModel.hasValue() )
+ lcl_dispose_nothrow( aOldSubModel );
+}
+
+
+OUString UnoGridModel::getServiceName()
+{
+ return "com.sun.star.awt.grid.UnoControlGridModel";
+}
+
+
+Any UnoGridModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString("com.sun.star.awt.grid.UnoControlGrid") );
+ case BASEPROPERTY_GRID_SELECTIONMODE:
+ return uno::Any( SelectionType(1) );
+ case BASEPROPERTY_GRID_SHOWROWHEADER:
+ case BASEPROPERTY_USE_GRID_LINES:
+ return uno::Any( false );
+ case BASEPROPERTY_ROW_HEADER_WIDTH:
+ return uno::Any( sal_Int32( 10 ) );
+ case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
+ return uno::Any( true );
+ case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
+ case BASEPROPERTY_ROW_HEIGHT:
+ case BASEPROPERTY_GRID_HEADER_BACKGROUND:
+ case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
+ case BASEPROPERTY_GRID_LINE_COLOR:
+ case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ return Any();
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+
+}
+
+
+::cppu::IPropertyArrayHelper& UnoGridModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+
+// XMultiPropertySet
+Reference< XPropertySetInfo > UnoGridModel::getPropertySetInfo( )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+
+//= UnoGridControl
+
+UnoGridControl::UnoGridControl()
+ :m_aSelectionListeners( *this )
+ ,m_pEventForwarder( new toolkit::GridEventForwarder( *this ) )
+{
+}
+
+
+UnoGridControl::~UnoGridControl()
+{
+}
+
+
+OUString UnoGridControl::GetComponentServiceName() const
+{
+ return "Grid";
+}
+
+
+void SAL_CALL UnoGridControl::dispose( )
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ m_aSelectionListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+
+void SAL_CALL UnoGridControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ const Reference< XGridRowSelection > xGrid( getPeer(), UNO_QUERY_THROW );
+ xGrid->addSelectionListener( &m_aSelectionListeners );
+}
+
+
+namespace
+{
+ void lcl_setEventForwarding( const Reference< XControlModel >& i_gridControlModel, const std::unique_ptr< toolkit::GridEventForwarder >& i_listener,
+ bool const i_add )
+ {
+ const Reference< XPropertySet > xModelProps( i_gridControlModel, UNO_QUERY );
+ if ( !xModelProps.is() )
+ return;
+
+ try
+ {
+ Reference< XContainer > const xColModel(
+ xModelProps->getPropertyValue("ColumnModel"),
+ UNO_QUERY_THROW );
+ if ( i_add )
+ xColModel->addContainerListener( i_listener.get() );
+ else
+ xColModel->removeContainerListener( i_listener.get() );
+
+ Reference< XGridDataModel > const xDataModel(
+ xModelProps->getPropertyValue("GridDataModel"),
+ UNO_QUERY_THROW
+ );
+ Reference< XMutableGridDataModel > const xMutableDataModel( xDataModel, UNO_QUERY );
+ if ( xMutableDataModel.is() )
+ {
+ if ( i_add )
+ xMutableDataModel->addGridDataListener( i_listener.get() );
+ else
+ xMutableDataModel->removeGridDataListener( i_listener.get() );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::setModel( const Reference< XControlModel >& i_model )
+{
+ lcl_setEventForwarding( getModel(), m_pEventForwarder, false );
+ if ( !UnoGridControl_Base::setModel( i_model ) )
+ return false;
+ lcl_setEventForwarding( getModel(), m_pEventForwarder, true );
+ return true;
+}
+
+
+::sal_Int32 UnoGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getRowAtPoint( x, y );
+}
+
+
+::sal_Int32 UnoGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getColumnAtPoint( x, y );
+}
+
+
+::sal_Int32 SAL_CALL UnoGridControl::getCurrentColumn( )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getCurrentColumn();
+}
+
+
+::sal_Int32 SAL_CALL UnoGridControl::getCurrentRow( )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getCurrentRow();
+}
+
+
+void SAL_CALL UnoGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ xGrid->goToCell( i_columnIndex, i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::selectRow( ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectRow( i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::selectAllRows()
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectAllRows();
+}
+
+
+void SAL_CALL UnoGridControl::deselectRow( ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectRow( i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::deselectAllRows()
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectAllRows();
+}
+
+
+css::uno::Sequence< ::sal_Int32 > SAL_CALL UnoGridControl::getSelectedRows()
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->getSelectedRows();
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::hasSelectedRows()
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->hasSelectedRows();
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::isRowSelected(::sal_Int32 index)
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->isRowSelected( index );
+}
+
+
+void SAL_CALL UnoGridControl::addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.addInterface( listener );
+}
+
+
+void SAL_CALL UnoGridControl::removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.removeInterface( listener );
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_GridControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoGridControl());
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_GridControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoGridModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcontrol.hxx b/toolkit/source/controls/grid/gridcontrol.hxx
new file mode 100644
index 000000000..6b4f8152b
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcontrol.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCONTROL_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCONTROL_HXX
+
+#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
+
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <memory>
+
+namespace toolkit
+{
+
+class GridEventForwarder;
+
+
+// = UnoGridModel
+
+class UnoGridModel : public UnoControlModel
+{
+protected:
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+ explicit UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoGridModel( const UnoGridModel& rModel );
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // OPropertySetHelper
+ void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ { return "stardiv.Toolkit.GridControlModel"; }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 1);
+ s.getArray()[s.getLength() - 1] = "com.sun.star.awt.grid.UnoControlGridModel";
+ return s;
+ }
+};
+
+
+// = UnoGridControl
+
+typedef ::cppu::ImplInheritanceHelper < UnoControlBase
+ , css::awt::grid::XGridControl
+ , css::awt::grid::XGridRowSelection
+ > UnoGridControl_Base;
+class UnoGridControl : public UnoGridControl_Base
+{
+public:
+ UnoGridControl();
+ OUString GetComponentServiceName() const override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::awt::XControl
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+ sal_Bool SAL_CALL setModel( const css::uno::Reference< css::awt::XControlModel >& rxModel ) override;
+
+ // css::awt::grid::XGridControl
+ virtual ::sal_Int32 SAL_CALL getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) override;
+ virtual ::sal_Int32 SAL_CALL getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) override;
+ virtual ::sal_Int32 SAL_CALL getCurrentColumn( ) override;
+ virtual ::sal_Int32 SAL_CALL getCurrentRow( ) override;
+ virtual void SAL_CALL goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) override;
+
+ // css::awt::grid::XGridRowSelection
+ virtual void SAL_CALL selectRow( ::sal_Int32 i_rowIndex ) override;
+ virtual void SAL_CALL selectAllRows() override;
+ virtual void SAL_CALL deselectRow( ::sal_Int32 i_rowIndex ) override;
+ virtual void SAL_CALL deselectAllRows() override;
+ virtual css::uno::Sequence< ::sal_Int32 > SAL_CALL getSelectedRows() override;
+ virtual sal_Bool SAL_CALL hasSelectedRows() override;
+ virtual sal_Bool SAL_CALL isRowSelected(::sal_Int32 index) override;
+ virtual void SAL_CALL addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener) override;
+ virtual void SAL_CALL removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ { return "stardiv.Toolkit.GridControl"; }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(UnoControlBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 1);
+ s.getArray()[s.getLength() - 1] = "com.sun.star.awt.grid.UnoControlGrid";
+ return s;
+ }
+
+ using UnoControl::getPeer;
+
+protected:
+ virtual ~UnoGridControl() override;
+
+private:
+ SelectionListenerMultiplexer m_aSelectionListeners;
+ std::unique_ptr< GridEventForwarder > m_pEventForwarder;
+};
+
+} // toolkit
+
+#endif // _TOOLKIT_TREE_CONTROL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/grideventforwarder.cxx b/toolkit/source/controls/grid/grideventforwarder.cxx
new file mode 100644
index 000000000..5baf5fdda
--- /dev/null
+++ b/toolkit/source/controls/grid/grideventforwarder.cxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include "grideventforwarder.hxx"
+#include "gridcontrol.hxx"
+
+
+namespace toolkit
+{
+
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::awt::grid::GridDataEvent;
+ using ::com::sun::star::container::ContainerEvent;
+ using ::com::sun::star::lang::EventObject;
+
+
+ //= GridEventForwarder
+
+
+ GridEventForwarder::GridEventForwarder( UnoGridControl& i_parent )
+ :m_parent( i_parent )
+ {
+ }
+
+
+ GridEventForwarder::~GridEventForwarder()
+ {
+ }
+
+
+ void SAL_CALL GridEventForwarder::acquire() noexcept
+ {
+ m_parent.acquire();
+ }
+
+
+ void SAL_CALL GridEventForwarder::release() noexcept
+ {
+ m_parent.release();
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowsInserted( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowsInserted( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowsRemoved( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowsRemoved( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::dataChanged( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->dataChanged( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowHeadingChanged( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowHeadingChanged( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementInserted( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementInserted( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementRemoved( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementRemoved( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementReplaced( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementReplaced( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::disposing( const EventObject& i_event )
+ {
+ Reference< XEventListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->disposing( i_event );
+ }
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/grideventforwarder.hxx b/toolkit/source/controls/grid/grideventforwarder.hxx
new file mode 100644
index 000000000..9578e62ee
--- /dev/null
+++ b/toolkit/source/controls/grid/grideventforwarder.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+
+#include <cppuhelper/implbase2.hxx>
+
+
+namespace toolkit
+{
+
+
+ class UnoGridControl;
+
+
+ //= GridEventForwarder
+
+ typedef ::cppu::ImplHelper2 < css::awt::grid::XGridDataListener
+ , css::container::XContainerListener
+ > GridEventForwarder_Base;
+
+ class GridEventForwarder : public GridEventForwarder_Base
+ {
+ public:
+ explicit GridEventForwarder( UnoGridControl& i_parent );
+ virtual ~GridEventForwarder();
+
+ public:
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XGridDataListener
+ virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
+
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
+
+ private:
+ UnoGridControl& m_parent;
+ };
+
+
+} // namespace toolkit
+
+
+#endif // INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/sortablegriddatamodel.cxx b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
new file mode 100644
index 000000000..6269d727d
--- /dev/null
+++ b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
@@ -0,0 +1,928 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <memory>
+#include <com/sun/star/i18n/Collator.hpp>
+#include <com/sun/star/i18n/XCollator.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/NotInitializedException.hpp>
+#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
+#include <com/sun/star/awt/grid/XSortableMutableGridDataModel.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/anycompare.hxx>
+#include <comphelper/componentguard.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace css::awt;
+using namespace css::awt::grid;
+using namespace css::i18n;
+using namespace css::lang;
+using namespace css::ucb;
+using namespace css::uno;
+
+namespace {
+
+class SortableGridDataModel;
+class MethodGuard;
+
+typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XSortableMutableGridDataModel
+ , css::lang::XServiceInfo
+ , css::lang::XInitialization
+ > SortableGridDataModel_Base;
+typedef ::cppu::ImplHelper1 < css::awt::grid::XGridDataListener
+ > SortableGridDataModel_PrivateBase;
+class SortableGridDataModel :public ::cppu::BaseMutex
+ ,public SortableGridDataModel_Base
+ ,public SortableGridDataModel_PrivateBase
+{
+public:
+ explicit SortableGridDataModel( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
+ SortableGridDataModel( SortableGridDataModel const & i_copySource );
+
+ bool isInitialized() const { return m_isInitialized; }
+
+protected:
+ virtual ~SortableGridDataModel() override;
+
+public:
+ // XSortableGridData
+ virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, sal_Bool SortAscending ) override;
+ virtual void SAL_CALL removeColumnSort( ) override;
+ virtual css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL getCurrentSortOrder( ) override;
+
+ // XMutableGridDataModel
+ virtual void SAL_CALL addRow( const css::uno::Any& Heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any >& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
+ virtual void SAL_CALL removeAllRows( ) override;
+ virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
+ virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
+ virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+ virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+
+ // XGridDataModel
+ virtual ::sal_Int32 SAL_CALL getRowCount() override;
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // XGridDataListener
+ virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept final override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+private:
+ /** translates the given public index into one to be passed to our delegator
+ @throws css::lang::IndexOutOfBoundsException
+ if the given index does not denote a valid row
+ */
+ ::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;
+
+ bool impl_isSorted_nothrow() const
+ {
+ return m_currentSortColumn >= 0;
+ }
+
+ /** rebuilds the index translation structure.
+
+ Neither <member>m_currentSortColumn</member> nor <member>m_sortAscending</member> are touched by this method.
+ Also, the given column index is not checked, this is the responsibility of the caller.
+ */
+ bool impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending );
+
+ /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
+ clients.
+ */
+ css::awt::grid::GridDataEvent
+ impl_createPublicEvent( css::awt::grid::GridDataEvent const & i_originalEvent ) const;
+
+ /** broadcasts the given event to our registered XGridDataListeners
+ */
+ void impl_broadcast(
+ void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( const css::awt::grid::GridDataEvent & ),
+ css::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 );
+
+ /** removes the current sorting, and notifies a change of all data
+ */
+ void impl_removeColumnSort( MethodGuard& i_instanceLock );
+
+ /** removes the current sorting, without any broadcast
+ */
+ void impl_removeColumnSort_noBroadcast();
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ bool m_isInitialized;
+ css::uno::Reference< css::awt::grid::XMutableGridDataModel > m_delegator;
+ css::uno::Reference< css::i18n::XCollator > m_collator;
+ ::sal_Int32 m_currentSortColumn;
+ bool m_sortAscending;
+ ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
+ ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
+};
+
+class MethodGuard : public ::comphelper::ComponentGuard
+{
+public:
+ MethodGuard( SortableGridDataModel& i_component, ::cppu::OBroadcastHelper & i_broadcastHelper )
+ :comphelper::ComponentGuard( i_component, i_broadcastHelper )
+ {
+ if ( !i_component.isInitialized() )
+ throw css::lang::NotInitializedException( OUString(), i_component );
+ }
+};
+
+template< class STLCONTAINER >
+void lcl_clear( STLCONTAINER& i_container )
+{
+ STLCONTAINER().swap(i_container);
+}
+
+ SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
+ :SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
+ ,m_xContext( rxContext )
+ ,m_isInitialized( false )
+ ,m_delegator()
+ ,m_collator()
+ ,m_currentSortColumn( -1 )
+ ,m_sortAscending( true )
+ ,m_publicToPrivateRowIndex()
+ ,m_privateToPublicRowIndex()
+ {
+ }
+
+
+ SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
+ :cppu::BaseMutex()
+ ,SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
+ ,m_xContext( i_copySource.m_xContext )
+ ,m_isInitialized( true )
+ ,m_delegator()
+ ,m_collator( i_copySource.m_collator )
+ ,m_currentSortColumn( i_copySource.m_currentSortColumn )
+ ,m_sortAscending( i_copySource.m_sortAscending )
+ ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
+ ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
+ {
+ 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 );
+ }
+
+
+ SortableGridDataModel::~SortableGridDataModel()
+ {
+ if ( !rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType )
+ {
+ Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
+ if ( !aReturn.hasValue() )
+ aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
+ return aReturn;
+ }
+
+
+ void SAL_CALL SortableGridDataModel::acquire( ) noexcept
+ {
+ SortableGridDataModel_Base::acquire();
+ }
+
+
+ void SAL_CALL SortableGridDataModel::release( ) noexcept
+ {
+ SortableGridDataModel_Base::release();
+ }
+
+
+ Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( )
+ {
+ 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( )
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
+ {
+ Reference< XCollator > const xCollator = Collator::create( rxContext );
+ xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
+ return xCollator;
+ }
+
+ void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( m_delegator.is() )
+ throw AlreadyInitializedException( OUString(), *this );
+
+ Reference< XMutableGridDataModel > xDelegator;
+ Reference< XCollator > xCollator;
+ switch ( i_arguments.getLength() )
+ {
+ case 1: // SortableGridDataModel.create( XMutableGridDataModel )
+ xDelegator.set( i_arguments[0], UNO_QUERY );
+ xCollator = lcl_loadDefaultCollator_throw( m_xContext );
+ break;
+
+ case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
+ xDelegator.set( i_arguments[0], UNO_QUERY );
+ xCollator.set( i_arguments[1], UNO_QUERY );
+ if ( !xCollator.is() )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+ break;
+ }
+ if ( !xDelegator.is() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ 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( cppu::UnoType<XGridDataListener>::get() );
+ if ( pListeners == nullptr )
+ return;
+
+ i_instanceLock.clear();
+ pListeners->notifyEach( i_listenerMethod, i_publicEvent );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ if ( impl_isSorted_nothrow() )
+ {
+ // no infrastructure is in place currently to sort the new row to its proper location,
+ // so we remove the sorting here.
+ impl_removeColumnSort( aGuard );
+ aGuard.reset();
+ }
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
+ }
+
+ void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
+ {
+ for ( auto& rIndex : io_indexMap )
+ {
+ if ( rIndex >= i_threshold )
+ --rIndex;
+ }
+ }
+
+ 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 );
+
+ // rebuild the index
+ if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
+ {
+ impl_removeColumnSort( i_instanceLock );
+ return;
+ }
+
+ // 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();
+
+ // 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 )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ // 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 ( o3tl::make_unsigned( 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 )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::disposing( const EventObject& )
+ {
+ }
+
+ class CellDataLessComparison
+ {
+ public:
+ CellDataLessComparison(
+ ::std::vector< Any > const & i_data,
+ ::comphelper::IKeyPredicateLess const & i_predicate,
+ bool const i_sortAscending
+ )
+ :m_data( i_data )
+ ,m_predicate( i_predicate )
+ ,m_sortAscending( i_sortAscending )
+ {
+ }
+
+ bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
+ {
+ Any const & lhs = m_data[ i_lhs ];
+ Any const & rhs = m_data[ i_rhs ];
+ // <VOID/> is less than everything else
+ if ( !lhs.hasValue() )
+ return m_sortAscending;
+ if ( !rhs.hasValue() )
+ return !m_sortAscending;
+
+ // actually compare
+ if ( m_sortAscending )
+ return m_predicate.isLess( lhs, rhs );
+ else
+ return m_predicate.isLess( rhs, lhs );
+ }
+
+ private:
+ ::std::vector< Any > const & m_data;
+ ::comphelper::IKeyPredicateLess const & m_predicate;
+ bool const m_sortAscending;
+ };
+
+ bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending )
+ {
+ ::sal_Int32 const rowCount( getRowCount() );
+ ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
+
+ try
+ {
+ // build an unsorted translation table, and retrieve the unsorted data
+ ::std::vector< Any > aColumnData( rowCount );
+ Type dataType;
+ for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
+ {
+ aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
+ aPublicToPrivate[ rowIndex ] = rowIndex;
+
+ // determine the data types we assume for the complete column
+ if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
+ dataType = aColumnData[ rowIndex ].getValueType();
+ }
+
+ // get predicate object
+ ::std::unique_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
+ ENSURE_OR_RETURN_FALSE(
+ pPredicate, "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!");
+
+ // then sort
+ CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
+ ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ return false;
+ }
+
+ // 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 );
+
+ return true;
+ }
+
+
+ void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, sal_Bool i_sortAscending )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
+ return;
+
+ m_currentSortColumn = i_columnIndex;
+ m_sortAscending = i_sortAscending;
+
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ aGuard
+ );
+ }
+
+
+ void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
+ {
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+
+ m_currentSortColumn = -1;
+ m_sortAscending = true;
+ }
+
+
+ void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
+ {
+ impl_removeColumnSort_noBroadcast();
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ i_instanceLock
+ );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeColumnSort( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ impl_removeColumnSort( aGuard );
+ }
+
+
+ css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ return css::beans::Pair< ::sal_Int32, sal_Bool >( m_currentSortColumn, m_sortAscending );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->addRow( i_heading, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->addRows( i_headings, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
+ // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->insertRow( rowIndex, i_heading, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
+ // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->insertRows( rowIndex, i_headings, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->removeRow( rowIndex );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeAllRows( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->removeAllRows();
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateCellData( i_columnIndex, rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowHeading( rowIndex, i_heading );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowToolTip( rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener )
+ {
+ rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener )
+ {
+ rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount()
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowCount();
+ }
+
+
+ ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount()
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getColumnCount();
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getCellData( i_columnIndex, rowIndex );
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getCellToolTip( i_columnIndex, rowIndex );
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowHeading( rowIndex );
+ }
+
+
+ Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowData( rowIndex );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::disposing()
+ {
+ m_currentSortColumn = -1;
+
+ Reference< XComponent > const delegatorComponent( m_delegator );
+ m_delegator->removeGridDataListener( this );
+ m_delegator.clear();
+ delegatorComponent->dispose();
+
+ Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
+ m_collator.clear();
+ if ( collatorComponent.is() )
+ collatorComponent->dispose();
+
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL SortableGridDataModel::createClone( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ return new SortableGridDataModel( *this );
+ }
+
+
+ OUString SAL_CALL SortableGridDataModel::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.SortableGridDataModel";
+ }
+
+ sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.SortableGridDataModel" };
+ }
+
+
+ ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
+ {
+ if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
+
+ if ( !impl_isSorted_nothrow() )
+ // no need to translate anything
+ return i_publicRowIndex;
+
+ ENSURE_OR_RETURN( o3tl::make_unsigned( 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_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( o3tl::make_unsigned( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
+ "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
+
+ return m_privateToPublicRowIndex[ i_privateRowIndex ];
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SortableGridDataModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */