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>
45#include <svx/strings.hrc>
54template<
class Vec,
class Iter >
static void remove_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
56 const sal_Int32 nSize =
static_cast<sal_Int32
>(rVector.size());
73template<
class Vec,
class Iter,
class Entry >
static sal_Int32
insert_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
77 if(
nIndex >=
static_cast< sal_Int32
>( rVector.size() ) )
80 nIndex =
static_cast< sal_Int32
>( rVector.size() );
86 Iter aIter( rVector.begin() );
87 std::advance( aIter,
nIndex );
90 rVector.insert( aIter,
nCount, aEmpty );
99, mpTableObj( pTableObj )
101, mbNotifyPending( false )
108, mpTableObj( pTableObj )
110, mbNotifyPending( false )
113 if( !xSourceTable.is() )
116 const sal_Int32 nColCount = xSourceTable->getColumnCountImpl();
117 const sal_Int32 nRowCount = xSourceTable->getRowCountImpl();
119 init( nColCount, nRowCount );
121 sal_Int32 nRows = nRowCount;
123 (*
maRows[nRows]) = *xSourceTable->maRows[nRows];
125 sal_Int32 nColumns = nColCount;
127 (*
maColumns[nColumns]) = *xSourceTable->maColumns[nColumns];
130 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
132 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
135 if( xTargetCell.is() )
136 xTargetCell->cloneFrom( xSourceTable->getCell( nCol, nRow ) );
155 if( nRows && nColumns )
217 const sal_Int32
nCount = sal::static_int_cast< sal_Int32 >( aRows.size() );
221 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
248 const sal_Int32
nCount = sal::static_int_cast< sal_Int32 >( aCols.size() );
251 DBG_ASSERT( (aCols.size() *
maRows.size()) == aCells.size(),
"sdr::table::TableModel::UndoRemoveColumns(), invalid undo data!" );
254 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
257 CellVector::iterator aIter( aCells.begin() );
260 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
262 CellVector::iterator aIter2 = aIter + nRow *
nCount;
263 OSL_ENSURE(aIter2 < aCells.end(),
"invalid iterator!");
286 ICellRange* pRange =
dynamic_cast< ICellRange*
>( rRange.get() );
287 if( (pRange ==
nullptr) || (pRange->getTable().get() !=
this) )
288 throw lang::IllegalArgumentException();
291 return new CellCursor(
xModel, pRange->getLeft(), pRange->getTop(), pRange->getRight(), pRange->getBottom() );
309 std::vector<sal_Int32> aRet;
311 aRet.push_back(
xColumn->getWidth());
321 TableModelBase::dispose();
395 throw lang::IndexOutOfBoundsException();
409 throw lang::IndexOutOfBoundsException();
415 return uno::Reference< XCellRange >();
424 uno::Reference<beans::XPropertySetInfo> xInfo;
480 return static_cast< sal_Int32
>(
maRows.size() );
486 return static_cast< sal_Int32
>(
maColumns.size() );
494 for(
auto& rpRow :
maRows )
547 ::osl::MutexGuard guard(
m_aMutex );
553 if( pModifyListeners )
555 lang::EventObject aSource;
556 aSource.Source = getXWeak();
557 pModifyListeners->
notifyEach(&util::XModifyListener::modified, aSource);
571 return maRows[nRow]->maCells[nCol];
606 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
610 aNewColumns[nOffset] = xNewCol;
624 CellVector::iterator aCellIter( aNewCells.begin() );
627 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
629 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
633 rModel.
AddUndo( std::make_unique<InsertColUndo>( xThis,
nIndex, aNewColumns, aNewCells ) );
638 for( sal_Int32 nCol = 0; nCol <
nIndex; ++nCol )
640 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
643 sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
644 if( (nColSpan != 1) && ((nColSpan + nCol ) >
nIndex) )
647 const sal_Int32 nRowSpan = xCell->getRowSpan();
649 merge( nCol, nRow, nColSpan, nRowSpan );
659 catch( uno::Exception& )
699 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
701 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
704 sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
717 if( xTargetCell.is() )
720 xTargetCell->AddUndo();
721 xTargetCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
722 xTargetCell->replaceContentAndFormatting( xCell );
726 else if( nColSpan > (
nIndex - nCol) )
729 const sal_Int32 nRemove = ::std::min(
nCount, nCol + nColSpan -
nIndex );
732 xCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
744 for( nOffset = 0; nOffset <
nCount; ++nOffset )
750 CellVector::iterator aCellIter( aRemovedCells.begin() );
751 for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
753 for( nOffset = 0; nOffset <
nCount; ++nOffset )
757 rModel.
AddUndo( std::make_unique<RemoveColUndo>( xThis,
nIndex, aRemovedCols, aRemovedCells ) );
770 catch( uno::Exception& )
796 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
800 aNewRows[nOffset] = xNewRow;
808 rModel.
AddUndo( std::make_unique<InsertRowUndo>( xThis,
nIndex, aNewRows ) );
812 for( sal_Int32 nRow = 0; nRow <
nIndex; ++nRow )
814 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
817 sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
818 if( (nRowSpan > 1) && ((nRowSpan + nRow) >
nIndex) )
821 const sal_Int32 nColSpan = xCell->getColumnSpan();
823 merge( nCol, nRow, nColSpan, nRowSpan );
828 catch( uno::Exception& )
872 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
874 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
877 sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
890 if( xTargetCell.is() )
893 xTargetCell->AddUndo();
894 xTargetCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
895 xTargetCell->replaceContentAndFormatting( xCell );
899 else if( nRowSpan > (
nIndex - nRow) )
902 const sal_Int32 nRemove = ::std::min(
nCount, nRow + nRowSpan -
nIndex );
905 xCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
915 for( sal_Int32 nOffset = 0; nOffset <
nCount; ++nOffset )
920 rModel.
AddUndo( std::make_unique<RemoveRowUndo>( xThis,
nIndex, aRemovedRows ) );
930 catch( uno::Exception& )
945 throw lang::IndexOutOfBoundsException();
954 throw lang::IndexOutOfBoundsException();
963 bool bWasModified =
false;
972 for( sal_Int32 nRow = 0; (nRow < nRows) && bEmpty; nRow++ )
974 uno::Reference<css::table::XMergeableCell> xCell(
getCellByPosition( nCol, nRow ), uno::UNO_QUERY );
975 if( xCell.is() && !xCell->isMerged() )
983 static constexpr OUStringLiteral sWidth(
u"Width");
984 sal_Int32 nWidth1 = 0, nWidth2 = 0;
985 uno::Reference<beans::XPropertySet> xSet1(
static_cast< XCellRange*
>(
maColumns[nCol].
get() ), uno::UNO_QUERY_THROW );
986 uno::Reference<beans::XPropertySet> xSet2(
static_cast< XCellRange*
>(
maColumns[nCol-1].
get() ), uno::UNO_QUERY_THROW );
987 xSet1->getPropertyValue( sWidth ) >>= nWidth1;
988 xSet2->getPropertyValue( sWidth ) >>= nWidth2;
990 xSet2->setPropertyValue( sWidth,
uno::Any( nWidth1 ) );
992 catch( uno::Exception& )
1009 for( nCol = 0; (nCol < nCols) && bEmpty; nCol++ )
1011 uno::Reference<css::table::XMergeableCell> xCell(
getCellByPosition( nCol, nRow ), uno::UNO_QUERY );
1012 if( xCell.is() && !xCell->isMerged() )
1020 static constexpr OUStringLiteral sHeight(
u"Height");
1021 sal_Int32 nHeight1 = 0, nHeight2 = 0;
1022 uno::Reference<beans::XPropertySet> xSet1(
static_cast< XCellRange*
>(
maRows[nRow].
get() ), uno::UNO_QUERY_THROW );
1023 uno::Reference<beans::XPropertySet> xSet2(
static_cast< XCellRange*
>(
maRows[nRow-1].
get() ), uno::UNO_QUERY_THROW );
1024 xSet1->getPropertyValue( sHeight ) >>= nHeight1;
1025 xSet2->getPropertyValue( sHeight ) >>= nHeight2;
1027 xSet2->setPropertyValue( sHeight,
uno::Any( nHeight1 ) );
1029 catch( uno::Exception& )
1035 bWasModified =
true;
1053 const sal_Int32 nLastRow = nRow + nRowSpan;
1054 const sal_Int32 nLastCol = nCol + nColSpan;
1058 OSL_FAIL(
"TableModel::merge(), merge beyond the table!");
1063 if(!xOriginCell.is())
1067 xOriginCell->AddUndo();
1068 xOriginCell->merge( nColSpan, nRowSpan );
1070 sal_Int32 nTempCol = nCol + 1;
1073 for( ; nRow < nLastRow; nRow++ )
1075 for( ; nTempCol < nLastCol; nTempCol++ )
1078 if( xCell.is() && !xCell->isMerged() )
1083 xOriginCell->mergeContent( xCell );
1093 for(
auto& rpRow :
maRows )
1095 rpRow->mnRow = nRow++;
1101 sal_Int32 nColumn = 0;
1104 rpCol->mnColumn = nColumn++;
1110 (void)xmlTextWriterStartElement(pWriter, BAD_CAST(
"TableModel"));
1114 maRows[nRow]->maCells[nCol]->dumpAsXml(pWriter, nRow, nCol);
1116 (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