22#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
23#include <com/sun/star/table/XMergeableCell.hpp>
28#include <osl/mutex.hxx>
29#include <libxml/xmlwriter.h>
35#include <tablemodel.hxx>
44#include <svx/strings.hrc>
53template<
class Vec,
class Iter >
static void remove_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
55 const sal_Int32 nSize =
static_cast<sal_Int32
>(rVector.size());
72template<
class Vec,
class Iter,
class Entry >
static sal_Int32
insert_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
76 if(
nIndex >=
static_cast< sal_Int32
>( rVector.size() ) )
79 nIndex =
static_cast< sal_Int32
>( rVector.size() );
85 Iter aIter( rVector.begin() );
86 std::advance( aIter,
nIndex );
89 rVector.insert( aIter,
nCount, aEmpty );
98, mpTableObj( pTableObj )
100, mbNotifyPending( false )
107, mpTableObj( pTableObj )
109, mbNotifyPending( false )
112 if( !xSourceTable.is() )
115 const sal_Int32 nColCount = xSourceTable->getColumnCountImpl();
116 const sal_Int32 nRowCount = xSourceTable->getRowCountImpl();
118 init( nColCount, nRowCount );
120 sal_Int32 nRows = nRowCount;
122 (*
maRows[nRows]) = *xSourceTable->maRows[nRows];
124 sal_Int32 nColumns = nColCount;
126 (*
maColumns[nColumns]) = *xSourceTable->maColumns[nColumns];
129 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
131 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
134 if( xTargetCell.is() )
135 xTargetCell->cloneFrom( xSourceTable->getCell( nCol, nRow ) );
154 if( nRows && nColumns )
216 const sal_Int32
nCount = sal::static_int_cast< sal_Int32 >( aRows.size() );
220 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
247 const sal_Int32
nCount = sal::static_int_cast< sal_Int32 >( aCols.size() );
250 DBG_ASSERT( (aCols.size() *
maRows.size()) == aCells.size(),
"sdr::table::TableModel::UndoRemoveColumns(), invalid undo data!" );
253 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
256 CellVector::iterator aIter( aCells.begin() );
259 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
261 CellVector::iterator aIter2 = aIter + nRow *
nCount;
262 OSL_ENSURE(aIter2 < aCells.end(),
"invalid iterator!");
285 ICellRange* pRange =
dynamic_cast< ICellRange*
>( rRange.get() );
286 if( (pRange ==
nullptr) || (pRange->getTable().get() !=
this) )
287 throw lang::IllegalArgumentException();
290 return new CellCursor(
xModel, pRange->getLeft(), pRange->getTop(), pRange->getRight(), pRange->getBottom() );
308 std::vector<sal_Int32> aRet;
310 aRet.push_back(
xColumn->getWidth());
320 TableModelBase::dispose();
394 throw lang::IndexOutOfBoundsException();
408 throw lang::IndexOutOfBoundsException();
414 return uno::Reference< XCellRange >();
423 uno::Reference<beans::XPropertySetInfo> xInfo;
479 return static_cast< sal_Int32
>(
maRows.size() );
485 return static_cast< sal_Int32
>(
maColumns.size() );
493 for(
auto& rpRow :
maRows )
546 ::osl::MutexGuard guard(
m_aMutex );
552 if( pModifyListeners )
554 lang::EventObject aSource;
556 pModifyListeners->
notifyEach(&util::XModifyListener::modified, aSource);
570 return maRows[nRow]->maCells[nCol];
605 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
609 aNewColumns[nOffset] = xNewCol;
623 CellVector::iterator aCellIter( aNewCells.begin() );
626 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
628 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
632 rModel.
AddUndo( std::make_unique<InsertColUndo>( xThis,
nIndex, aNewColumns, aNewCells ) );
637 for( sal_Int32 nCol = 0; nCol <
nIndex; ++nCol )
639 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
642 sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
643 if( (nColSpan != 1) && ((nColSpan + nCol ) >
nIndex) )
646 const sal_Int32 nRowSpan = xCell->getRowSpan();
648 merge( nCol, nRow, nColSpan, nRowSpan );
658 catch( uno::Exception& )
698 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
700 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
703 sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
716 if( xTargetCell.is() )
719 xTargetCell->AddUndo();
720 xTargetCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
721 xTargetCell->replaceContentAndFormatting( xCell );
725 else if( nColSpan > (
nIndex - nCol) )
728 const sal_Int32 nRemove = ::std::min(
nCount, nCol + nColSpan -
nIndex );
731 xCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
743 for( nOffset = 0; nOffset <
nCount; ++nOffset )
749 CellVector::iterator aCellIter( aRemovedCells.begin() );
750 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
752 for( nOffset = 0; nOffset <
nCount; ++nOffset )
756 rModel.
AddUndo( std::make_unique<RemoveColUndo>( xThis,
nIndex, aRemovedCols, aRemovedCells ) );
769 catch( uno::Exception& )
795 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
799 aNewRows[nOffset] = xNewRow;
807 rModel.
AddUndo( std::make_unique<InsertRowUndo>( xThis,
nIndex, aNewRows ) );
811 for( sal_Int32 nRow = 0; nRow <
nIndex; ++nRow )
813 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
816 sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
817 if( (nRowSpan > 1) && ((nRowSpan + nRow) >
nIndex) )
820 const sal_Int32 nColSpan = xCell->getColumnSpan();
822 merge( nCol, nRow, nColSpan, nRowSpan );
827 catch( uno::Exception& )
871 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
873 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
876 sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
889 if( xTargetCell.is() )
892 xTargetCell->AddUndo();
893 xTargetCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
894 xTargetCell->replaceContentAndFormatting( xCell );
898 else if( nRowSpan > (
nIndex - nRow) )
901 const sal_Int32 nRemove = ::std::min(
nCount, nRow + nRowSpan -
nIndex );
904 xCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
914 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
919 rModel.
AddUndo( std::make_unique<RemoveRowUndo>( xThis,
nIndex, aRemovedRows ) );
929 catch( uno::Exception& )
944 throw lang::IndexOutOfBoundsException();
953 throw lang::IndexOutOfBoundsException();
962 bool bWasModified =
false;
971 for( sal_Int32 nRow = 0; (nRow < nRows) && bEmpty; nRow++ )
973 uno::Reference<css::table::XMergeableCell> xCell(
getCellByPosition( nCol, nRow ), uno::UNO_QUERY );
974 if( xCell.is() && !xCell->isMerged() )
982 static const OUStringLiteral sWidth(
u"Width");
983 sal_Int32 nWidth1 = 0, nWidth2 = 0;
984 uno::Reference<beans::XPropertySet> xSet1(
static_cast< XCellRange*
>(
maColumns[nCol].
get() ), uno::UNO_QUERY_THROW );
985 uno::Reference<beans::XPropertySet> xSet2(
static_cast< XCellRange*
>(
maColumns[nCol-1].
get() ), uno::UNO_QUERY_THROW );
986 xSet1->getPropertyValue( sWidth ) >>= nWidth1;
987 xSet2->getPropertyValue( sWidth ) >>= nWidth2;
989 xSet2->setPropertyValue( sWidth,
uno::Any( nWidth1 ) );
991 catch( uno::Exception& )
1008 for( nCol = 0; (nCol < nCols) && bEmpty; nCol++ )
1010 uno::Reference<css::table::XMergeableCell> xCell(
getCellByPosition( nCol, nRow ), uno::UNO_QUERY );
1011 if( xCell.is() && !xCell->isMerged() )
1019 static const OUStringLiteral sHeight(
u"Height");
1020 sal_Int32 nHeight1 = 0, nHeight2 = 0;
1021 uno::Reference<beans::XPropertySet> xSet1(
static_cast< XCellRange*
>(
maRows[nRow].
get() ), uno::UNO_QUERY_THROW );
1022 uno::Reference<beans::XPropertySet> xSet2(
static_cast< XCellRange*
>(
maRows[nRow-1].
get() ), uno::UNO_QUERY_THROW );
1023 xSet1->getPropertyValue( sHeight ) >>= nHeight1;
1024 xSet2->getPropertyValue( sHeight ) >>= nHeight2;
1026 xSet2->setPropertyValue( sHeight,
uno::Any( nHeight1 ) );
1028 catch( uno::Exception& )
1034 bWasModified =
true;
1052 const sal_Int32 nLastRow = nRow + nRowSpan;
1053 const sal_Int32 nLastCol = nCol + nColSpan;
1057 OSL_FAIL(
"TableModel::merge(), merge beyond the table!");
1062 if(!xOriginCell.is())
1066 xOriginCell->AddUndo();
1067 xOriginCell->merge( nColSpan, nRowSpan );
1069 sal_Int32 nTempCol = nCol + 1;
1072 for( ; nRow < nLastRow; nRow++ )
1074 for( ; nTempCol < nLastCol; nTempCol++ )
1077 if( xCell.is() && !xCell->isMerged() )
1082 xOriginCell->mergeContent( xCell );
1092 for(
auto& rpRow :
maRows )
1094 rpRow->mnRow = nRow++;
1100 sal_Int32 nColumn = 0;
1103 rpCol->mnColumn = nColumn++;
1109 (void)xmlTextWriterStartElement(pWriter, BAD_CAST(
"TableModel"));
1113 maRows[nRow]->maCells[nCol]->dumpAsXml(pWriter, nRow, nCol);
1115 (void)xmlTextWriterEndElement(pWriter);
virtual void SetChanged(bool bFlg=true)
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
SdrUndoFactory & GetSdrUndoFactory() const
returns the models undo factory.
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
SdrModel & getSdrModelFromSdrObject() const
virtual std::unique_ptr< SdrUndoAction > CreateUndoGeoObject(SdrObject &rObject)
mutable::osl::Mutex m_aMutex
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
void createCell(sdr::table::CellRef &xCell)
void insertRows(sal_Int32 nIndex, sal_Int32 nCount)
virtual void SAL_CALL removePropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override
rtl::Reference< TableRows > mxTableRows
virtual css::uno::Reference< css::table::XTableColumns > SAL_CALL getColumns() override
virtual sal_Bool SAL_CALL isModified() override
void notifyModification()
void insertColumns(sal_Int32 nIndex, sal_Int32 nCount)
virtual void SAL_CALL lockBroadcasts() override
void removeRows(sal_Int32 nIndex, sal_Int32 nCount)
virtual ::sal_Int32 SAL_CALL getColumnCount() override
friend class TableColumns
virtual css::uno::Reference< css::table::XCell > SAL_CALL getCellByPosition(::sal_Int32 nColumn, ::sal_Int32 nRow) override
sal_Int32 getRowCountImpl() const
virtual css::uno::Any SAL_CALL getFastPropertyValue(::sal_Int32 nHandle) override
virtual ~TableModel() override
void init(sal_Int32 nColumns, sal_Int32 nRows)
virtual sal_Int32 getRight() override
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
TableColumnRef const & getColumn(sal_Int32 nColumn) const
virtual void SAL_CALL setFastPropertyValue(::sal_Int32 nHandle, const css::uno::Any &aValue) override
virtual css::uno::Reference< css::table::XTable > getTable() override
CellRef getCell(::sal_Int32 nCol, ::sal_Int32 nRow) const
virtual void SAL_CALL setModified(sal_Bool bModified) override
virtual css::uno::Reference< css::table::XCellRange > SAL_CALL getCellRangeByPosition(::sal_Int32 nLeft, ::sal_Int32 nTop, ::sal_Int32 nRight, ::sal_Int32 nBottom) override
virtual css::uno::Reference< css::table::XCellCursor > SAL_CALL createCursorByRange(const css::uno::Reference< css::table::XCellRange > &rRange) override
void merge(sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan)
merges the cell at the given position with the given span
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
virtual css::uno::Reference< css::table::XTableRows > SAL_CALL getRows() override
virtual void SAL_CALL unlockBroadcasts() override
virtual sal_Int32 getLeft() override
virtual css::uno::Reference< css::table::XCellRange > SAL_CALL getCellRangeByName(const OUString &aRange) override
void UndoInsertColumns(sal_Int32 nIndex, sal_Int32 nCount)
TableRowRef const & getRow(sal_Int32 nRow) const
std::vector< sal_Int32 > getColumnWidths()
Get the width of all columns in this table.
virtual sal_Int32 getBottom() override
virtual css::uno::Reference< css::table::XCellCursor > SAL_CALL createCursor() override
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
virtual void SAL_CALL dispose() override
virtual sal_Int32 getTop() override
virtual void SAL_CALL disposing() override
this function is called upon disposing the component
void removeColumns(sal_Int32 nIndex, sal_Int32 nCount)
void optimize()
deletes rows and columns that are completely merged.
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
rtl::Reference< TableColumns > mxTableColumns
TableModel(SdrTableObj *pTableObj)
void UndoInsertRows(sal_Int32 nIndex, sal_Int32 nCount)
sal_Int32 getColumnCountImpl() const
virtual void SAL_CALL removeVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
void UndoRemoveColumns(sal_Int32 nIndex, ColumnVector &aNewCols, CellVector &aCells)
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
virtual ::sal_Int32 SAL_CALL getRowCount() override
void dumpAsXml(xmlTextWriterPtr pWriter) const
void UndoRemoveRows(sal_Int32 nIndex, RowVector &aNewRows)
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString SvxResId(TranslateId aId)
struct _xmlTextWriter * xmlTextWriterPtr
constexpr T saturating_add(T a, T b)
std::vector< CellRef > CellVector
static void remove_range(Vec &rVector, sal_Int32 nIndex, sal_Int32 nCount)
static sal_Int32 insert_range(Vec &rVector, sal_Int32 nIndex, sal_Int32 nCount)
inserts a range into a vector
std::vector< TableColumnRef > ColumnVector
std::vector< TableRowRef > RowVector
::cppu::WeakComponentImplHelper< css::table::XTable, css::util::XBroadcaster > TableModelBase
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Reference< XModel > xModel