2010-10-12 15:53:47 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-11-21 22:06:52 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
2008-03-12 09:05:12 +00:00
|
|
|
*
|
2012-11-21 22:06:52 +00:00
|
|
|
* 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/.
|
2008-03-12 09:05:12 +00:00
|
|
|
*
|
2012-11-21 22:06:52 +00:00
|
|
|
* This file incorporates work covered by the following license notice:
|
2008-03-12 09:05:12 +00:00
|
|
|
*
|
2012-11-21 22:06:52 +00:00
|
|
|
* 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 .
|
|
|
|
*/
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
#include <com/sun/star/table/XMergeableCell.hpp>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include <vcl/svapp.hxx>
|
2010-10-16 03:18:35 -05:00
|
|
|
#include <osl/mutex.hxx>
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
#include "cell.hxx"
|
|
|
|
#include "cellcursor.hxx"
|
|
|
|
#include "tablemodel.hxx"
|
|
|
|
#include "tablerow.hxx"
|
|
|
|
#include "tablerows.hxx"
|
|
|
|
#include "tablecolumn.hxx"
|
|
|
|
#include "tablecolumns.hxx"
|
|
|
|
#include "tableundo.hxx"
|
|
|
|
#include "svx/svdotable.hxx"
|
|
|
|
#include "svx/svdmodel.hxx"
|
2010-04-20 15:55:51 +02:00
|
|
|
#include "svx/svdstr.hrc"
|
|
|
|
#include "svx/svdglob.hxx"
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
using ::rtl::OUString;
|
|
|
|
using namespace ::osl;
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
|
|
using namespace ::com::sun::star::table;
|
|
|
|
using namespace ::com::sun::star::lang;
|
|
|
|
using namespace ::com::sun::star::container;
|
|
|
|
using namespace ::com::sun::star::beans;
|
|
|
|
using namespace ::com::sun::star::util;
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace sdr { namespace table {
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// removes the given range from a vector
|
|
|
|
template< class Vec, class Iter > void remove_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
const sal_Int32 nSize = static_cast<sal_Int32>(rVector.size());
|
|
|
|
if( nCount && (nIndex >= 0) && (nIndex < nSize) )
|
|
|
|
{
|
|
|
|
if( (nIndex + nCount) >= nSize )
|
|
|
|
{
|
|
|
|
// remove at end
|
|
|
|
rVector.resize( nIndex );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Iter aBegin( rVector.begin() );
|
|
|
|
while( nIndex-- )
|
|
|
|
aBegin++;
|
|
|
|
if( nCount == 1 )
|
|
|
|
{
|
|
|
|
rVector.erase( aBegin );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Iter aEnd( aBegin );
|
|
|
|
|
|
|
|
while( nCount-- )
|
|
|
|
aEnd++;
|
|
|
|
rVector.erase( aBegin, aEnd );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/** inserts a range into a vector */
|
2008-03-14 10:26:44 +00:00
|
|
|
template< class Vec, class Iter, class Entry > sal_Int32 insert_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
if( nCount )
|
|
|
|
{
|
|
|
|
if( nIndex >= static_cast< sal_Int32 >( rVector.size() ) )
|
|
|
|
{
|
|
|
|
// append at end
|
|
|
|
nIndex = static_cast< sal_Int32 >( rVector.size() ); // cap to end
|
|
|
|
rVector.resize( nIndex + nCount );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// insert
|
|
|
|
sal_Int32 nFind = nIndex;
|
|
|
|
Iter aIter( rVector.begin() );
|
|
|
|
while( nFind-- )
|
2013-03-30 17:42:34 +01:00
|
|
|
++aIter;
|
2008-03-14 10:26:44 +00:00
|
|
|
|
|
|
|
Entry aEmpty;
|
|
|
|
rVector.insert( aIter, nCount, aEmpty );
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TableModel::TableModel( SdrTableObj* pTableObj )
|
|
|
|
: TableModelBase( m_aMutex )
|
|
|
|
, mpTableObj( pTableObj )
|
|
|
|
, mbModified( sal_False )
|
|
|
|
, mbNotifyPending( false )
|
|
|
|
, mnNotifyLock( 0 )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TableModel::TableModel( SdrTableObj* pTableObj, const TableModelRef& xSourceTable )
|
|
|
|
: TableModelBase( m_aMutex )
|
|
|
|
, mpTableObj( pTableObj )
|
|
|
|
, mbModified( sal_False )
|
|
|
|
, mbNotifyPending( false )
|
|
|
|
, mnNotifyLock( 0 )
|
|
|
|
{
|
|
|
|
if( xSourceTable.is() )
|
|
|
|
{
|
|
|
|
const sal_Int32 nColCount = xSourceTable->getColumnCountImpl();
|
|
|
|
const sal_Int32 nRowCount = xSourceTable->getRowCountImpl();
|
|
|
|
|
|
|
|
init( nColCount, nRowCount );
|
|
|
|
|
|
|
|
sal_Int32 nRows = nRowCount;
|
|
|
|
while( nRows-- )
|
|
|
|
(*maRows[nRows]) = (*xSourceTable->maRows[nRows]);
|
|
|
|
|
|
|
|
sal_Int32 nColumns = nColCount;
|
|
|
|
while( nColumns-- )
|
|
|
|
(*maColumns[nColumns]) = (*xSourceTable->maColumns[nColumns]);
|
|
|
|
|
|
|
|
// copy cells
|
|
|
|
for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
|
|
|
|
{
|
|
|
|
CellRef xTargetCell( getCell( nCol, nRow ) );
|
|
|
|
if( xTargetCell.is() )
|
|
|
|
xTargetCell->cloneFrom( xSourceTable->getCell( nCol, nRow ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TableModel::~TableModel()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::init( sal_Int32 nColumns, sal_Int32 nRows )
|
|
|
|
{
|
|
|
|
if( nRows < 20 )
|
|
|
|
maRows.reserve( 20 );
|
|
|
|
|
|
|
|
if( nColumns < 20 )
|
|
|
|
maColumns.reserve( 20 );
|
|
|
|
|
|
|
|
if( nRows && nColumns )
|
|
|
|
{
|
|
|
|
maColumns.resize( nColumns );
|
|
|
|
maRows.resize( nRows );
|
|
|
|
|
|
|
|
while( nRows-- )
|
|
|
|
maRows[nRows].set( new TableRow( this, nRows, nColumns ) );
|
|
|
|
|
|
|
|
while( nColumns-- )
|
|
|
|
maColumns[nColumns].set( new TableColumn( this, nColumns ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// ICellRange
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getLeft()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getTop()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getRight()
|
|
|
|
{
|
|
|
|
return getColumnCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getBottom()
|
|
|
|
{
|
|
|
|
return getRowCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XTable > TableModel::getTable()
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::UndoInsertRows( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
// remove the rows
|
|
|
|
remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
|
2008-11-20 14:55:36 +00:00
|
|
|
updateRows();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::UndoRemoveRows( sal_Int32 nIndex, RowVector& aRows )
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aRows.size() );
|
|
|
|
|
2008-03-14 10:26:44 +00:00
|
|
|
nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
maRows[nIndex+nOffset] = aRows[nOffset];
|
|
|
|
|
2008-11-20 14:55:36 +00:00
|
|
|
updateRows();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::UndoInsertColumns( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
// now remove the columns
|
|
|
|
remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
|
|
|
|
sal_Int32 nRows = getRowCountImpl();
|
|
|
|
while( nRows-- )
|
|
|
|
maRows[nRows]->removeColumns( nIndex, nCount );
|
2008-11-20 14:55:36 +00:00
|
|
|
|
|
|
|
updateColumns();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::UndoRemoveColumns( sal_Int32 nIndex, ColumnVector& aCols, CellVector& aCells )
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aCols.size() );
|
|
|
|
|
|
|
|
// assert if there are not enough cells saved
|
|
|
|
DBG_ASSERT( (aCols.size() * maRows.size()) == aCells.size(), "sdr::table::TableModel::UndoRemoveColumns(), invalid undo data!" );
|
|
|
|
|
2008-03-14 10:26:44 +00:00
|
|
|
nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
|
2008-03-12 09:05:12 +00:00
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
maColumns[nIndex+nOffset] = aCols[nOffset];
|
|
|
|
|
|
|
|
CellVector::iterator aIter( aCells.begin() );
|
|
|
|
|
|
|
|
sal_Int32 nRows = getRowCountImpl();
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
|
2012-11-21 22:06:52 +00:00
|
|
|
{
|
|
|
|
CellVector::iterator aIter2 = aIter + nRow * nCount;
|
|
|
|
OSL_ENSURE(aIter2 < aCells.end(), "invalid iterator!");
|
|
|
|
maRows[nRow]->insertColumns( nIndex, nCount, &aIter2 );
|
|
|
|
}
|
2008-11-20 14:55:36 +00:00
|
|
|
|
|
|
|
updateColumns();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XTable
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XCellCursor > SAL_CALL TableModel::createCursor() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
return createCursorByRange( Reference< XCellRange >( this ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2012-12-25 15:18:26 +01:00
|
|
|
Reference< XCellCursor > SAL_CALL TableModel::createCursorByRange( const Reference< XCellRange >& rRange ) throw (IllegalArgumentException, RuntimeException)
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
|
2012-12-25 15:18:26 +01:00
|
|
|
ICellRange* pRange = dynamic_cast< ICellRange* >( rRange.get() );
|
2008-03-12 09:05:12 +00:00
|
|
|
if( (pRange == 0) || (pRange->getTable().get() != this) )
|
|
|
|
throw IllegalArgumentException();
|
|
|
|
|
|
|
|
TableModelRef xModel( this );
|
|
|
|
return new CellCursor( xModel, pRange->getLeft(), pRange->getTop(), pRange->getRight(), pRange->getBottom() );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 SAL_CALL TableModel::getRowCount() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
return getRowCountImpl();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 SAL_CALL TableModel::getColumnCount() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
return getColumnCountImpl();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XComponent
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::dispose() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
TableModelBase::dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
TableModelBase::addEventListener( xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
TableModelBase::removeEventListener( xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XModifiable
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Bool SAL_CALL TableModel::isModified( ) throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
return mbModified;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::setModified( sal_Bool bModified ) throw (PropertyVetoException, RuntimeException)
|
|
|
|
{
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
mbModified = bModified;
|
|
|
|
}
|
|
|
|
if( bModified )
|
|
|
|
notifyModification();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XModifyBroadcaster
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::addModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
rBHelper.addListener( XModifyListener::static_type() , xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::removeModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
rBHelper.removeListener( XModifyListener::static_type() , xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XColumnRowRange
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XTableColumns > SAL_CALL TableModel::getColumns() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
if( !mxTableColumns.is() )
|
|
|
|
mxTableColumns.set( new TableColumns( this ) );
|
|
|
|
return mxTableColumns.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XTableRows > SAL_CALL TableModel::getRows() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
if( !mxTableRows.is() )
|
|
|
|
mxTableRows.set( new TableRows( this ) );
|
|
|
|
return mxTableRows.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XCellRange
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XCell > SAL_CALL TableModel::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw ( IndexOutOfBoundsException, RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
CellRef xCell( getCell( nColumn, nRow ) );
|
|
|
|
if( xCell.is() )
|
|
|
|
return xCell.get();
|
|
|
|
|
|
|
|
throw IndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XCellRange > SAL_CALL TableModel::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) throw (IndexOutOfBoundsException, RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
if( (nLeft >= 0) && (nTop >= 0) && (nRight >= nLeft) && (nBottom >= nTop) && (nRight < getColumnCountImpl()) && (nBottom < getRowCountImpl() ) )
|
|
|
|
{
|
|
|
|
TableModelRef xModel( this );
|
|
|
|
return new CellRange( xModel, nLeft, nTop, nRight, nBottom );
|
|
|
|
}
|
|
|
|
|
|
|
|
throw IndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XCellRange > SAL_CALL TableModel::getCellRangeByName( const OUString& /*aRange*/ ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
return Reference< XCellRange >();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XPropertySet
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Reference< XPropertySetInfo > SAL_CALL TableModel::getPropertySetInfo( ) throw (RuntimeException)
|
|
|
|
{
|
|
|
|
Reference< XPropertySetInfo > xInfo;
|
|
|
|
return xInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::setPropertyValue( const ::rtl::OUString& /*aPropertyName*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Any SAL_CALL TableModel::getPropertyValue( const OUString& /*PropertyName*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
return Any();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::addVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::removeVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XFastPropertySet
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void SAL_CALL TableModel::setFastPropertyValue( ::sal_Int32 /*nHandle*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
Any SAL_CALL TableModel::getFastPropertyValue( ::sal_Int32 /*nHandle*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
|
|
|
|
{
|
|
|
|
Any aAny;
|
|
|
|
return aAny;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// internals
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getRowCountImpl() const
|
|
|
|
{
|
|
|
|
return static_cast< sal_Int32 >( maRows.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
sal_Int32 TableModel::getColumnCountImpl() const
|
|
|
|
{
|
|
|
|
return static_cast< sal_Int32 >( maColumns.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::disposing()
|
|
|
|
{
|
|
|
|
if( !maRows.empty() )
|
|
|
|
{
|
|
|
|
RowVector::iterator aIter( maRows.begin() );
|
|
|
|
while( aIter != maRows.end() )
|
|
|
|
(*aIter++)->dispose();
|
|
|
|
RowVector().swap(maRows);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !maColumns.empty() )
|
|
|
|
{
|
|
|
|
ColumnVector::iterator aIter( maColumns.begin() );
|
|
|
|
while( aIter != maColumns.end() )
|
|
|
|
(*aIter++)->dispose();
|
|
|
|
ColumnVector().swap(maColumns);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( mxTableColumns.is() )
|
|
|
|
{
|
|
|
|
mxTableColumns->dispose();
|
|
|
|
mxTableColumns.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( mxTableRows.is() )
|
|
|
|
{
|
|
|
|
mxTableRows->dispose();
|
|
|
|
mxTableRows.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
mpTableObj = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// XBroadcaster
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::lockBroadcasts() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
++mnNotifyLock;
|
|
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::unlockBroadcasts() throw (RuntimeException)
|
|
|
|
{
|
2010-10-16 03:18:35 -05:00
|
|
|
::SolarMutexGuard aGuard;
|
2008-03-12 09:05:12 +00:00
|
|
|
--mnNotifyLock;
|
|
|
|
if( mnNotifyLock <= 0 )
|
|
|
|
{
|
|
|
|
mnNotifyLock = 0;
|
|
|
|
if( mbNotifyPending )
|
|
|
|
notifyModification();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TableModel::notifyModification()
|
|
|
|
{
|
|
|
|
::osl::MutexGuard guard( m_aMutex );
|
|
|
|
if( (mnNotifyLock == 0) && mpTableObj && mpTableObj->GetModel() )
|
|
|
|
{
|
2009-06-17 10:58:14 +00:00
|
|
|
mbNotifyPending = false;
|
|
|
|
|
|
|
|
::cppu::OInterfaceContainerHelper * pModifyListeners = rBHelper.getContainer( XModifyListener::static_type() );
|
|
|
|
if( pModifyListeners )
|
|
|
|
{
|
|
|
|
EventObject aSource;
|
|
|
|
aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
|
|
|
|
pModifyListeners->notifyEach( &XModifyListener::modified, aSource);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mbNotifyPending = true;
|
|
|
|
}
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
CellRef TableModel::getCell( sal_Int32 nCol, sal_Int32 nRow ) const
|
|
|
|
{
|
|
|
|
if( ((nRow >= 0) && (nRow < getRowCountImpl())) && (nCol >= 0) && (nCol < getColumnCountImpl()) )
|
|
|
|
{
|
|
|
|
return maRows[nRow]->maCells[nCol];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CellRef xRet;
|
|
|
|
return xRet;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
CellRef TableModel::createCell()
|
|
|
|
{
|
|
|
|
CellRef xCell;
|
|
|
|
if( mpTableObj )
|
|
|
|
mpTableObj->createCell( xCell );
|
|
|
|
return xCell;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::insertColumns( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
if( nCount && mpTableObj )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
SdrModel* pModel = mpTableObj->GetModel();
|
|
|
|
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
2008-03-14 10:26:44 +00:00
|
|
|
nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
sal_Int32 nRows = getRowCountImpl();
|
|
|
|
while( nRows-- )
|
|
|
|
maRows[nRows]->insertColumns( nIndex, nCount );
|
|
|
|
|
|
|
|
ColumnVector aNewColumns(nCount);
|
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
{
|
|
|
|
TableColumnRef xNewCol( new TableColumn( this, nIndex+nOffset ) );
|
|
|
|
maColumns[nIndex+nOffset] = xNewCol;
|
|
|
|
aNewColumns[nOffset] = xNewCol;
|
|
|
|
}
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
|
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
pModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
|
|
|
|
pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
|
|
|
|
|
|
|
|
TableModelRef xThis( this );
|
|
|
|
|
|
|
|
nRows = getRowCountImpl();
|
|
|
|
CellVector aNewCells( nCount * nRows );
|
|
|
|
CellVector::iterator aCellIter( aNewCells.begin() );
|
|
|
|
|
|
|
|
nRows = getRowCountImpl();
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
(*aCellIter++) = getCell( nIndex + nOffset, nRow );
|
|
|
|
}
|
|
|
|
|
|
|
|
pModel->AddUndo( new InsertColUndo( xThis, nIndex, aNewColumns, aNewCells ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
const sal_Int32 nRowCount = getRowCountImpl();
|
|
|
|
// check if cells merge over new columns
|
|
|
|
for( sal_Int32 nCol = 0; nCol < nIndex; ++nCol )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
|
|
|
|
{
|
|
|
|
CellRef xCell( getCell( nCol, nRow ) );
|
|
|
|
sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
|
|
|
|
if( (nColSpan != 1) && ((nColSpan + nCol ) > nIndex) )
|
|
|
|
{
|
|
|
|
// cell merges over newly created columns, so add the new columns to the merged cell
|
|
|
|
const sal_Int32 nRowSpan = xCell->getRowSpan();
|
|
|
|
nColSpan += nCount;
|
2009-06-17 10:58:14 +00:00
|
|
|
merge( nCol, nRow, nColSpan, nRowSpan );
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
pModel->EndUndo();
|
|
|
|
|
2009-09-09 09:19:53 +00:00
|
|
|
if( pModel )
|
|
|
|
pModel->SetChanged();
|
|
|
|
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
catch( Exception& )
|
|
|
|
{
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("sdr::table::TableModel::insertColumns(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
2008-11-20 14:55:36 +00:00
|
|
|
updateColumns();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::removeColumns( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
sal_Int32 nColCount = getColumnCountImpl();
|
|
|
|
|
|
|
|
if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nColCount) )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
// clip removed columns to columns actually avalaible
|
|
|
|
if( (nIndex + nCount) > nColCount )
|
|
|
|
nCount = nColCount - nIndex;
|
|
|
|
|
|
|
|
sal_Int32 nRows = getRowCountImpl();
|
|
|
|
|
|
|
|
SdrModel* pModel = mpTableObj->GetModel();
|
2009-06-04 16:21:29 +00:00
|
|
|
|
|
|
|
const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
|
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
pModel->BegUndo( ImpGetResStr(STR_UNDO_COL_DELETE) );
|
|
|
|
pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
|
|
|
|
|
|
|
|
TableModelRef xThis( this );
|
|
|
|
ColumnVector aRemovedCols( nCount );
|
|
|
|
sal_Int32 nOffset;
|
|
|
|
for( nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
{
|
|
|
|
aRemovedCols[nOffset] = maColumns[nIndex+nOffset];
|
|
|
|
}
|
|
|
|
|
|
|
|
CellVector aRemovedCells( nCount * nRows );
|
|
|
|
CellVector::iterator aCellIter( aRemovedCells.begin() );
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
|
|
|
|
{
|
|
|
|
for( nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
(*aCellIter++) = getCell( nIndex + nOffset, nRow );
|
|
|
|
}
|
|
|
|
|
|
|
|
pModel->AddUndo( new RemoveColUndo( xThis, nIndex, aRemovedCols, aRemovedCells ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// only rows before and inside the removed rows are considered
|
|
|
|
nColCount = nIndex + nCount + 1;
|
|
|
|
|
|
|
|
const sal_Int32 nRowCount = getRowCountImpl();
|
|
|
|
|
|
|
|
// first check merged cells before and inside the removed rows
|
|
|
|
for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
|
|
|
|
{
|
|
|
|
CellRef xCell( getCell( nCol, nRow ) );
|
|
|
|
sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
|
|
|
|
if( nColSpan <= 1 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( nCol >= nIndex )
|
|
|
|
{
|
|
|
|
// current cell is inside the removed columns
|
|
|
|
if( (nCol + nColSpan) > ( nIndex + nCount ) )
|
|
|
|
{
|
|
|
|
// current cells merges with columns after the removed columns
|
|
|
|
const sal_Int32 nRemove = nCount - nCol + nIndex;
|
|
|
|
|
|
|
|
CellRef xTargetCell( getCell( nIndex + nCount, nRow ) );
|
|
|
|
if( xTargetCell.is() )
|
|
|
|
{
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
|
|
|
xTargetCell->AddUndo();
|
2008-03-12 09:05:12 +00:00
|
|
|
xTargetCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
|
|
|
|
xTargetCell->replaceContentAndFormating( xCell );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( nColSpan > (nIndex - nCol) )
|
|
|
|
{
|
|
|
|
// current cells spans inside the removed columns, so adjust
|
|
|
|
const sal_Int32 nRemove = ::std::min( nCount, nCol + nColSpan - nIndex );
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
xCell->AddUndo();
|
|
|
|
xCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now remove the columns
|
|
|
|
remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
|
|
|
|
while( nRows-- )
|
|
|
|
maRows[nRows]->removeColumns( nIndex, nCount );
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
pModel->EndUndo();
|
2009-09-09 09:19:53 +00:00
|
|
|
|
|
|
|
if( pModel )
|
2009-06-17 10:58:14 +00:00
|
|
|
pModel->SetChanged();
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
catch( Exception& )
|
|
|
|
{
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("sdr::table::TableModel::removeColumns(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
|
2008-11-20 14:55:36 +00:00
|
|
|
updateColumns();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::insertRows( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
if( nCount && mpTableObj )
|
|
|
|
{
|
2008-11-20 14:55:36 +00:00
|
|
|
SdrModel* pModel = mpTableObj->GetModel();
|
2009-06-04 16:21:29 +00:00
|
|
|
const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
|
2008-03-12 09:05:12 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
2008-03-14 10:26:44 +00:00
|
|
|
nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
|
2008-03-12 09:05:12 +00:00
|
|
|
|
|
|
|
RowVector aNewRows(nCount);
|
|
|
|
const sal_Int32 nColCount = getColumnCountImpl();
|
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
{
|
|
|
|
TableRowRef xNewRow( new TableRow( this, nIndex+nOffset, nColCount ) );
|
|
|
|
maRows[nIndex+nOffset] = xNewRow;
|
|
|
|
aNewRows[nOffset] = xNewRow;
|
|
|
|
}
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
|
|
|
{
|
2008-03-12 09:05:12 +00:00
|
|
|
pModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW) );
|
|
|
|
pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
|
|
|
|
TableModelRef xThis( this );
|
|
|
|
pModel->AddUndo( new InsertRowUndo( xThis, nIndex, aNewRows ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if cells merge over new columns
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nIndex; ++nRow )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
|
|
|
|
{
|
|
|
|
CellRef xCell( getCell( nCol, nRow ) );
|
|
|
|
sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
|
|
|
|
if( (nRowSpan > 1) && ((nRowSpan + nRow) > nIndex) )
|
|
|
|
{
|
|
|
|
// cell merges over newly created columns, so add the new columns to the merged cell
|
|
|
|
const sal_Int32 nColSpan = xCell->getColumnSpan();
|
|
|
|
nRowSpan += nCount;
|
2009-06-17 10:58:14 +00:00
|
|
|
merge( nCol, nRow, nColSpan, nRowSpan );
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch( Exception& )
|
|
|
|
{
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("sdr::table::TableModel::insertRows(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-11-20 14:55:36 +00:00
|
|
|
pModel->EndUndo();
|
|
|
|
|
2009-09-09 09:19:53 +00:00
|
|
|
if( pModel )
|
|
|
|
pModel->SetChanged();
|
|
|
|
|
2008-11-20 14:55:36 +00:00
|
|
|
updateRows();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::removeRows( sal_Int32 nIndex, sal_Int32 nCount )
|
|
|
|
{
|
|
|
|
sal_Int32 nRowCount = getRowCountImpl();
|
|
|
|
|
|
|
|
if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nRowCount) )
|
|
|
|
{
|
2009-06-04 16:21:29 +00:00
|
|
|
SdrModel* pModel = mpTableObj->GetModel();
|
|
|
|
const bool bUndo = pModel && mpTableObj->IsInserted()&& pModel->IsUndoEnabled();
|
|
|
|
|
2008-03-12 09:05:12 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
// clip removed rows to rows actually avalaible
|
|
|
|
if( (nIndex + nCount) > nRowCount )
|
|
|
|
nCount = nRowCount - nIndex;
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
pModel->BegUndo( ImpGetResStr(STR_UNDO_ROW_DELETE) );
|
|
|
|
pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
|
|
|
|
|
|
|
|
TableModelRef xThis( this );
|
|
|
|
|
|
|
|
RowVector aRemovedRows( nCount );
|
|
|
|
for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
|
|
|
|
aRemovedRows[nOffset] = maRows[nIndex+nOffset];
|
|
|
|
|
|
|
|
pModel->AddUndo( new RemoveRowUndo( xThis, nIndex, aRemovedRows ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// only rows before and inside the removed rows are considered
|
|
|
|
nRowCount = nIndex + nCount + 1;
|
|
|
|
|
|
|
|
const sal_Int32 nColCount = getColumnCountImpl();
|
|
|
|
|
|
|
|
// first check merged cells before and inside the removed rows
|
|
|
|
for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
|
|
|
|
{
|
|
|
|
for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
|
|
|
|
{
|
|
|
|
CellRef xCell( getCell( nCol, nRow ) );
|
|
|
|
sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
|
|
|
|
if( nRowSpan <= 1 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( nRow >= nIndex )
|
|
|
|
{
|
|
|
|
// current cell is inside the removed rows
|
|
|
|
if( (nRow + nRowSpan) > (nIndex + nCount) )
|
|
|
|
{
|
|
|
|
// current cells merges with rows after the removed rows
|
|
|
|
const sal_Int32 nRemove = nCount - nRow + nIndex;
|
|
|
|
|
|
|
|
CellRef xTargetCell( getCell( nCol, nIndex + nCount ) );
|
|
|
|
if( xTargetCell.is() )
|
|
|
|
{
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
|
|
|
xTargetCell->AddUndo();
|
2008-03-12 09:05:12 +00:00
|
|
|
xTargetCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
|
|
|
|
xTargetCell->replaceContentAndFormating( xCell );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( nRowSpan > (nIndex - nRow) )
|
|
|
|
{
|
|
|
|
// current cells spans inside the removed rows, so adjust
|
|
|
|
const sal_Int32 nRemove = ::std::min( nCount, nRow + nRowSpan - nIndex );
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
|
|
|
xCell->AddUndo();
|
2008-03-12 09:05:12 +00:00
|
|
|
xCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now remove the rows
|
|
|
|
remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
if( bUndo )
|
2008-03-12 09:05:12 +00:00
|
|
|
pModel->EndUndo();
|
2009-09-09 09:19:53 +00:00
|
|
|
|
|
|
|
if( pModel )
|
2009-06-17 10:58:14 +00:00
|
|
|
pModel->SetChanged();
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
catch( Exception& )
|
|
|
|
{
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("sdr::table::TableModel::removeRows(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
|
2008-11-20 14:55:36 +00:00
|
|
|
updateRows();
|
2008-03-12 09:05:12 +00:00
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TableRowRef TableModel::getRow( sal_Int32 nRow ) const throw (IndexOutOfBoundsException)
|
|
|
|
{
|
|
|
|
if( (nRow >= 0) && (nRow < getRowCountImpl()) )
|
|
|
|
return maRows[nRow];
|
|
|
|
|
|
|
|
throw IndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
TableColumnRef TableModel::getColumn( sal_Int32 nColumn ) const throw (IndexOutOfBoundsException)
|
|
|
|
{
|
|
|
|
if( (nColumn >= 0) && (nColumn < getColumnCountImpl()) )
|
|
|
|
return maColumns[nColumn];
|
|
|
|
|
|
|
|
throw IndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2013-03-03 17:11:39 +01:00
|
|
|
/** deletes rows and columns that are completely merged. Must be called between BegUndo/EndUndo! */
|
2008-03-12 09:05:12 +00:00
|
|
|
void TableModel::optimize()
|
|
|
|
{
|
|
|
|
TableModelNotifyGuard aGuard( this );
|
|
|
|
|
|
|
|
bool bWasModified = false;
|
|
|
|
|
|
|
|
if( !maRows.empty() && !maColumns.empty() )
|
|
|
|
{
|
|
|
|
sal_Int32 nCol = getColumnCountImpl() - 1;
|
2013-01-07 13:50:23 +03:00
|
|
|
sal_Int32 nRows = getRowCountImpl();
|
2008-03-12 09:05:12 +00:00
|
|
|
while( nCol > 0 )
|
|
|
|
{
|
|
|
|
bool bEmpty = true;
|
2013-01-07 13:50:23 +03:00
|
|
|
for( sal_Int32 nRow = 0; (nRow < nRows) && bEmpty; nRow++ )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
|
|
|
|
if( xCell.is() && !xCell->isMerged() )
|
|
|
|
bEmpty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bEmpty )
|
|
|
|
{
|
|
|
|
if( nCol > 0 ) try
|
|
|
|
{
|
2013-03-19 11:39:07 +01:00
|
|
|
const OUString sWidth("Width");
|
2008-03-12 09:05:12 +00:00
|
|
|
sal_Int32 nWidth1 = 0, nWidth2 = 0;
|
|
|
|
Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maColumns[nCol].get() ), UNO_QUERY_THROW );
|
|
|
|
Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maColumns[nCol-1].get() ), UNO_QUERY_THROW );
|
|
|
|
xSet1->getPropertyValue( sWidth ) >>= nWidth1;
|
|
|
|
xSet2->getPropertyValue( sWidth ) >>= nWidth2;
|
|
|
|
nWidth1 += nWidth2;
|
|
|
|
xSet2->setPropertyValue( sWidth, Any( nWidth1 ) );
|
|
|
|
}
|
|
|
|
catch( Exception& e )
|
|
|
|
{
|
|
|
|
(void)e;
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("svx::TableModel::optimize(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
removeColumns( nCol, 1 );
|
|
|
|
bWasModified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nCol--;
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_Int32 nRow = getRowCountImpl() - 1;
|
2013-01-07 13:50:23 +03:00
|
|
|
sal_Int32 nCols = getColumnCountImpl();
|
2008-03-12 09:05:12 +00:00
|
|
|
while( nRow > 0 )
|
|
|
|
{
|
|
|
|
bool bEmpty = true;
|
2013-01-07 13:50:23 +03:00
|
|
|
for( nCol = 0; (nCol < nCols) && bEmpty; nCol++ )
|
2008-03-12 09:05:12 +00:00
|
|
|
{
|
|
|
|
Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
|
|
|
|
if( xCell.is() && !xCell->isMerged() )
|
|
|
|
bEmpty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bEmpty )
|
|
|
|
{
|
|
|
|
if( nRow > 0 ) try
|
|
|
|
{
|
2013-03-19 11:39:07 +01:00
|
|
|
const OUString sHeight("Height");
|
2008-03-12 09:05:12 +00:00
|
|
|
sal_Int32 nHeight1 = 0, nHeight2 = 0;
|
|
|
|
Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maRows[nRow].get() ), UNO_QUERY_THROW );
|
|
|
|
Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maRows[nRow-1].get() ), UNO_QUERY_THROW );
|
|
|
|
xSet1->getPropertyValue( sHeight ) >>= nHeight1;
|
|
|
|
xSet2->getPropertyValue( sHeight ) >>= nHeight2;
|
|
|
|
nHeight1 += nHeight2;
|
|
|
|
xSet2->setPropertyValue( sHeight, Any( nHeight1 ) );
|
|
|
|
}
|
|
|
|
catch( Exception& e )
|
|
|
|
{
|
|
|
|
(void)e;
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("svx::TableModel::optimize(), exception caught!");
|
2008-03-12 09:05:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
removeRows( nRow, 1 );
|
|
|
|
bWasModified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nRow--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( bWasModified )
|
|
|
|
setModified(sal_True);
|
|
|
|
}
|
|
|
|
|
2009-06-17 10:58:14 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::merge( sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
|
|
|
|
{
|
2009-06-22 10:18:07 +00:00
|
|
|
SdrModel* pModel = mpTableObj->GetModel();
|
|
|
|
|
2009-06-17 10:58:14 +00:00
|
|
|
const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
|
|
|
|
|
|
|
|
const sal_Int32 nLastRow = nRow + nRowSpan;
|
|
|
|
const sal_Int32 nLastCol = nCol + nColSpan;
|
|
|
|
|
2013-01-07 13:56:08 +03:00
|
|
|
if( (nLastRow > getRowCount()) || (nLastCol > getColumnCount() ) )
|
2009-06-17 10:58:14 +00:00
|
|
|
{
|
2011-03-01 19:07:44 +01:00
|
|
|
OSL_FAIL("TableModel::merge(), merge beyound the table!");
|
2009-06-17 10:58:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// merge first cell
|
|
|
|
CellRef xOriginCell( dynamic_cast< Cell* >( getCellByPosition( nCol, nRow ).get() ) );
|
|
|
|
if( xOriginCell.is() )
|
|
|
|
{
|
|
|
|
if( bUndo )
|
|
|
|
xOriginCell->AddUndo();
|
|
|
|
xOriginCell->merge( nColSpan, nRowSpan );
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_Int32 nTempCol = nCol + 1;
|
|
|
|
|
|
|
|
// merge remaining cells
|
|
|
|
for( ; nRow < nLastRow; nRow++ )
|
|
|
|
{
|
|
|
|
for( ; nTempCol < nLastCol; nTempCol++ )
|
|
|
|
{
|
|
|
|
CellRef xCell( dynamic_cast< Cell* >( getCellByPosition( nTempCol, nRow ).get() ) );
|
|
|
|
if( xCell.is() && !xCell->isMerged() )
|
|
|
|
{
|
|
|
|
if( bUndo )
|
|
|
|
xCell->AddUndo();
|
|
|
|
xCell->setMerged();
|
|
|
|
xOriginCell->mergeContent( xCell );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nTempCol = nCol;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-12 09:05:12 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2008-11-20 14:55:36 +00:00
|
|
|
void TableModel::updateRows()
|
|
|
|
{
|
|
|
|
sal_Int32 nRow = 0;
|
|
|
|
RowVector::iterator iter = maRows.begin();
|
|
|
|
while( iter != maRows.end() )
|
|
|
|
{
|
|
|
|
(*iter++)->mnRow = nRow++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void TableModel::updateColumns()
|
|
|
|
{
|
|
|
|
sal_Int32 nColumn = 0;
|
|
|
|
ColumnVector::iterator iter = maColumns.begin();
|
|
|
|
while( iter != maColumns.end() )
|
|
|
|
{
|
|
|
|
(*iter++)->mnColumn = nColumn++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
2008-03-12 09:05:12 +00:00
|
|
|
} }
|
2010-10-12 15:53:47 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|