xref: /AOO41X/main/svx/source/table/tablemodel.cxx (revision 04f4019c437c8e2792962dc7c04252117eb65c03)
1f6e50924SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3f6e50924SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4f6e50924SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5f6e50924SAndrew Rist  * distributed with this work for additional information
6f6e50924SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7f6e50924SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8f6e50924SAndrew Rist  * "License"); you may not use this file except in compliance
9f6e50924SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11f6e50924SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13f6e50924SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14f6e50924SAndrew Rist  * software distributed under the License is distributed on an
15f6e50924SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16f6e50924SAndrew Rist  * KIND, either express or implied.  See the License for the
17f6e50924SAndrew Rist  * specific language governing permissions and limitations
18f6e50924SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20f6e50924SAndrew Rist  *************************************************************/
21f6e50924SAndrew Rist 
22f6e50924SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <com/sun/star/table/XMergeableCell.hpp>
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <algorithm>
30cdf0e10cSrcweir #include <boost/bind.hpp>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <vcl/svapp.hxx>
33cdf0e10cSrcweir #include <vos/mutex.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "cell.hxx"
36cdf0e10cSrcweir #include "cellcursor.hxx"
37cdf0e10cSrcweir #include "tablemodel.hxx"
38cdf0e10cSrcweir #include "tablerow.hxx"
39cdf0e10cSrcweir #include "tablerows.hxx"
40cdf0e10cSrcweir #include "tablecolumn.hxx"
41cdf0e10cSrcweir #include "tablecolumns.hxx"
42cdf0e10cSrcweir #include "tableundo.hxx"
43cdf0e10cSrcweir #include "svx/svdotable.hxx"
44cdf0e10cSrcweir #include "svx/svdmodel.hxx"
45cdf0e10cSrcweir #include "svx/svdstr.hrc"
46cdf0e10cSrcweir #include "svx/svdglob.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir //#define PLEASE_DEBUG_THE_TABLES 1
49cdf0e10cSrcweir 
50cdf0e10cSrcweir using ::rtl::OUString;
51cdf0e10cSrcweir using namespace ::osl;
52cdf0e10cSrcweir using namespace ::vos;
53cdf0e10cSrcweir using namespace ::com::sun::star::uno;
54cdf0e10cSrcweir using namespace ::com::sun::star::table;
55cdf0e10cSrcweir using namespace ::com::sun::star::lang;
56cdf0e10cSrcweir using namespace ::com::sun::star::container;
57cdf0e10cSrcweir using namespace ::com::sun::star::beans;
58cdf0e10cSrcweir using namespace ::com::sun::star::util;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir // -----------------------------------------------------------------------------
61cdf0e10cSrcweir 
62cdf0e10cSrcweir namespace sdr { namespace table {
63cdf0e10cSrcweir 
64cdf0e10cSrcweir // -----------------------------------------------------------------------------
65cdf0e10cSrcweir 
66cdf0e10cSrcweir // removes the given range from a vector
remove_range(Vec & rVector,sal_Int32 nIndex,sal_Int32 nCount)67cdf0e10cSrcweir template< class Vec, class Iter > void remove_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
68cdf0e10cSrcweir {
69cdf0e10cSrcweir 	const sal_Int32 nSize = static_cast<sal_Int32>(rVector.size());
70cdf0e10cSrcweir 	if( nCount && (nIndex >= 0) && (nIndex < nSize) )
71cdf0e10cSrcweir 	{
72cdf0e10cSrcweir 		if( (nIndex + nCount) >= nSize )
73cdf0e10cSrcweir 		{
74cdf0e10cSrcweir 			// remove at end
75cdf0e10cSrcweir 			rVector.resize( nIndex );
76cdf0e10cSrcweir 		}
77cdf0e10cSrcweir 		else
78cdf0e10cSrcweir 		{
79cdf0e10cSrcweir 			Iter aBegin( rVector.begin() );
80cdf0e10cSrcweir 			while( nIndex-- )
81cdf0e10cSrcweir 				aBegin++;
82cdf0e10cSrcweir 			if( nCount == 1 )
83cdf0e10cSrcweir 			{
84cdf0e10cSrcweir 				rVector.erase( aBegin );
85cdf0e10cSrcweir 			}
86cdf0e10cSrcweir 			else
87cdf0e10cSrcweir 			{
88cdf0e10cSrcweir 				Iter aEnd( aBegin );
89cdf0e10cSrcweir 
90cdf0e10cSrcweir 				while( nCount-- )
91cdf0e10cSrcweir 					aEnd++;
92cdf0e10cSrcweir 				rVector.erase( aBegin, aEnd );
93cdf0e10cSrcweir 			}
94cdf0e10cSrcweir 		}
95cdf0e10cSrcweir 	}
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
98cdf0e10cSrcweir // -----------------------------------------------------------------------------
99cdf0e10cSrcweir 
100cdf0e10cSrcweir /** inserts a range into a vector */
insert_range(Vec & rVector,sal_Int32 nIndex,sal_Int32 nCount)101cdf0e10cSrcweir template< class Vec, class Iter, class Entry > sal_Int32 insert_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir 	if( nCount )
104cdf0e10cSrcweir 	{
105cdf0e10cSrcweir 		if( nIndex >= static_cast< sal_Int32 >( rVector.size() ) )
106cdf0e10cSrcweir 		{
107cdf0e10cSrcweir 			// append at end
108cdf0e10cSrcweir 			nIndex = static_cast< sal_Int32 >( rVector.size() ); // cap to end
109cdf0e10cSrcweir 			rVector.resize( nIndex + nCount );
110cdf0e10cSrcweir 		}
111cdf0e10cSrcweir 		else
112cdf0e10cSrcweir 		{
113cdf0e10cSrcweir 			// insert
114cdf0e10cSrcweir 			sal_Int32 nFind = nIndex;
115cdf0e10cSrcweir 			Iter aIter( rVector.begin() );
116cdf0e10cSrcweir 			while( nFind-- )
117cdf0e10cSrcweir 				aIter++;
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 			Entry aEmpty;
120cdf0e10cSrcweir 			rVector.insert( aIter, nCount, aEmpty );
121cdf0e10cSrcweir 		}
122cdf0e10cSrcweir 	}
123cdf0e10cSrcweir 	return nIndex;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir // -----------------------------------------------------------------------------
127cdf0e10cSrcweir 
TableModel(SdrTableObj * pTableObj)128cdf0e10cSrcweir TableModel::TableModel( SdrTableObj* pTableObj )
129cdf0e10cSrcweir : TableModelBase( m_aMutex  )
130cdf0e10cSrcweir , mpTableObj( pTableObj )
131cdf0e10cSrcweir , mbModified( sal_False )
132cdf0e10cSrcweir , mbNotifyPending( false )
133cdf0e10cSrcweir , mnNotifyLock( 0 )
134cdf0e10cSrcweir {
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
TableModel(SdrTableObj * pTableObj,const TableModelRef & xSourceTable)137cdf0e10cSrcweir TableModel::TableModel( SdrTableObj* pTableObj, const TableModelRef& xSourceTable )
138cdf0e10cSrcweir : TableModelBase( m_aMutex  )
139cdf0e10cSrcweir , mpTableObj( pTableObj )
140cdf0e10cSrcweir , mbModified( sal_False )
141cdf0e10cSrcweir , mbNotifyPending( false )
142cdf0e10cSrcweir , mnNotifyLock( 0 )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir 	if( xSourceTable.is() )
145cdf0e10cSrcweir 	{
146cdf0e10cSrcweir 		const sal_Int32 nColCount = xSourceTable->getColumnCountImpl();
147cdf0e10cSrcweir 		const sal_Int32 nRowCount = xSourceTable->getRowCountImpl();
148cdf0e10cSrcweir 
149cdf0e10cSrcweir 		init( nColCount, nRowCount );
150cdf0e10cSrcweir 
151cdf0e10cSrcweir 		sal_Int32 nRows = nRowCount;
152cdf0e10cSrcweir 		while( nRows-- )
153cdf0e10cSrcweir 			(*maRows[nRows]) = (*xSourceTable->maRows[nRows]);
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 		sal_Int32 nColumns = nColCount;
156cdf0e10cSrcweir 		while( nColumns-- )
157cdf0e10cSrcweir 			(*maColumns[nColumns]) = (*xSourceTable->maColumns[nColumns]);
158cdf0e10cSrcweir 
159cdf0e10cSrcweir 		// copy cells
160cdf0e10cSrcweir 		for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
161cdf0e10cSrcweir 		{
162cdf0e10cSrcweir 			for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
163cdf0e10cSrcweir 			{
164cdf0e10cSrcweir 				CellRef xTargetCell( getCell( nCol, nRow ) );
165cdf0e10cSrcweir 				if( xTargetCell.is() )
166cdf0e10cSrcweir 					xTargetCell->cloneFrom( xSourceTable->getCell( nCol, nRow ) );
167cdf0e10cSrcweir 			}
168cdf0e10cSrcweir 		}
169cdf0e10cSrcweir 	}
170cdf0e10cSrcweir }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir // -----------------------------------------------------------------------------
173cdf0e10cSrcweir 
~TableModel()174cdf0e10cSrcweir TableModel::~TableModel()
175cdf0e10cSrcweir {
176cdf0e10cSrcweir }
177cdf0e10cSrcweir 
178cdf0e10cSrcweir // -----------------------------------------------------------------------------
179cdf0e10cSrcweir 
init(sal_Int32 nColumns,sal_Int32 nRows)180cdf0e10cSrcweir void TableModel::init( sal_Int32 nColumns, sal_Int32 nRows )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir 	if( nRows < 20 )
183cdf0e10cSrcweir 		maRows.reserve( 20 );
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 	if( nColumns < 20 )
186cdf0e10cSrcweir 		maColumns.reserve( 20 );
187cdf0e10cSrcweir 
188cdf0e10cSrcweir 	if( nRows && nColumns )
189cdf0e10cSrcweir 	{
190cdf0e10cSrcweir 		maColumns.resize( nColumns );
191cdf0e10cSrcweir 		maRows.resize( nRows );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir 		while( nRows-- )
194cdf0e10cSrcweir 			maRows[nRows].set( new TableRow( this, nRows, nColumns ) );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir 		while( nColumns-- )
197cdf0e10cSrcweir 			maColumns[nColumns].set( new TableColumn( this, nColumns ) );
198cdf0e10cSrcweir 	}
199cdf0e10cSrcweir }
200cdf0e10cSrcweir 
201cdf0e10cSrcweir // -----------------------------------------------------------------------------
202cdf0e10cSrcweir // ICellRange
203cdf0e10cSrcweir // -----------------------------------------------------------------------------
204cdf0e10cSrcweir 
getLeft()205cdf0e10cSrcweir sal_Int32 TableModel::getLeft()
206cdf0e10cSrcweir {
207cdf0e10cSrcweir 	return 0;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir 
210cdf0e10cSrcweir // -----------------------------------------------------------------------------
211cdf0e10cSrcweir 
getTop()212cdf0e10cSrcweir sal_Int32 TableModel::getTop()
213cdf0e10cSrcweir {
214cdf0e10cSrcweir 	return 0;
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir // -----------------------------------------------------------------------------
218cdf0e10cSrcweir 
getRight()219cdf0e10cSrcweir sal_Int32 TableModel::getRight()
220cdf0e10cSrcweir {
221cdf0e10cSrcweir 	return getColumnCount();
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir // -----------------------------------------------------------------------------
225cdf0e10cSrcweir 
getBottom()226cdf0e10cSrcweir sal_Int32 TableModel::getBottom()
227cdf0e10cSrcweir {
228cdf0e10cSrcweir 	return getRowCount();
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
231cdf0e10cSrcweir // -----------------------------------------------------------------------------
232cdf0e10cSrcweir 
getTable()233cdf0e10cSrcweir Reference< XTable > TableModel::getTable()
234cdf0e10cSrcweir {
235cdf0e10cSrcweir 	return this;
236cdf0e10cSrcweir }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir // -----------------------------------------------------------------------------
239cdf0e10cSrcweir 
UndoInsertRows(sal_Int32 nIndex,sal_Int32 nCount)240cdf0e10cSrcweir void TableModel::UndoInsertRows( sal_Int32 nIndex, sal_Int32 nCount )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir 	TableModelNotifyGuard aGuard( this );
243cdf0e10cSrcweir 
244cdf0e10cSrcweir 	// remove the rows
245cdf0e10cSrcweir 	remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
246cdf0e10cSrcweir     updateRows();
247cdf0e10cSrcweir 	setModified(sal_True);
248cdf0e10cSrcweir }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir // -----------------------------------------------------------------------------
251cdf0e10cSrcweir 
UndoRemoveRows(sal_Int32 nIndex,RowVector & aRows)252cdf0e10cSrcweir void TableModel::UndoRemoveRows( sal_Int32 nIndex, RowVector& aRows )
253cdf0e10cSrcweir {
254cdf0e10cSrcweir 	TableModelNotifyGuard aGuard( this );
255cdf0e10cSrcweir 
256cdf0e10cSrcweir 	const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aRows.size() );
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 	nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 	for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
261cdf0e10cSrcweir 		maRows[nIndex+nOffset] = aRows[nOffset];
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     updateRows();
264cdf0e10cSrcweir 	setModified(sal_True);
265cdf0e10cSrcweir }
266cdf0e10cSrcweir 
267cdf0e10cSrcweir // -----------------------------------------------------------------------------
268cdf0e10cSrcweir 
UndoInsertColumns(sal_Int32 nIndex,sal_Int32 nCount)269cdf0e10cSrcweir void TableModel::UndoInsertColumns( sal_Int32 nIndex, sal_Int32 nCount )
270cdf0e10cSrcweir {
271cdf0e10cSrcweir 	TableModelNotifyGuard aGuard( this );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 	// now remove the columns
274cdf0e10cSrcweir 	remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
275cdf0e10cSrcweir 	sal_Int32 nRows = getRowCountImpl();
276cdf0e10cSrcweir 	while( nRows-- )
277cdf0e10cSrcweir 		maRows[nRows]->removeColumns( nIndex, nCount );
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     updateColumns();
280cdf0e10cSrcweir 	setModified(sal_True);
281cdf0e10cSrcweir }
282cdf0e10cSrcweir 
283cdf0e10cSrcweir // -----------------------------------------------------------------------------
284cdf0e10cSrcweir 
UndoRemoveColumns(sal_Int32 nIndex,ColumnVector & aCols,CellVector & aCells)285cdf0e10cSrcweir void TableModel::UndoRemoveColumns( sal_Int32 nIndex, ColumnVector& aCols, CellVector& aCells )
286cdf0e10cSrcweir {
287cdf0e10cSrcweir 	TableModelNotifyGuard aGuard( this );
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 	const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aCols.size() );
290cdf0e10cSrcweir 
291cdf0e10cSrcweir 	// assert if there are not enough cells saved
292cdf0e10cSrcweir 	DBG_ASSERT( (aCols.size() * maRows.size()) == aCells.size(), "sdr::table::TableModel::UndoRemoveColumns(), invalid undo data!" );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 	nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
295cdf0e10cSrcweir 	for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
296cdf0e10cSrcweir 		maColumns[nIndex+nOffset] = aCols[nOffset];
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	CellVector::iterator aIter( aCells.begin() );
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 	sal_Int32 nRows = getRowCountImpl();
301cdf0e10cSrcweir 	for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
302*04f4019cSWang Lei 	{
303*04f4019cSWang Lei 		CellVector::iterator aIter2 = aIter + nRow * nCount;
304*04f4019cSWang Lei 		DBG_ASSERT(aIter2 < aCells.end(), "sdr::table::TableModel::UndoRemoveColumns(), invalid iterator!");
305*04f4019cSWang Lei 		maRows[nRow]->insertColumns( nIndex, nCount, &aIter2 );
306*04f4019cSWang Lei 	}
307cdf0e10cSrcweir 
308cdf0e10cSrcweir     updateColumns();
309cdf0e10cSrcweir 	setModified(sal_True);
310cdf0e10cSrcweir }
311cdf0e10cSrcweir 
312cdf0e10cSrcweir // -----------------------------------------------------------------------------
313cdf0e10cSrcweir // XTable
314cdf0e10cSrcweir // -----------------------------------------------------------------------------
315cdf0e10cSrcweir 
createCursor()316cdf0e10cSrcweir Reference< XCellCursor > SAL_CALL TableModel::createCursor() throw (RuntimeException)
317cdf0e10cSrcweir {
318cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
319cdf0e10cSrcweir 	return createCursorByRange( Reference< XCellRange >( this ) );
320cdf0e10cSrcweir }
321cdf0e10cSrcweir 
322cdf0e10cSrcweir // -----------------------------------------------------------------------------
323cdf0e10cSrcweir 
createCursorByRange(const Reference<XCellRange> & Range)324cdf0e10cSrcweir Reference< XCellCursor > SAL_CALL TableModel::createCursorByRange( const Reference< XCellRange >& Range ) throw (IllegalArgumentException, RuntimeException)
325cdf0e10cSrcweir {
326cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 	ICellRange* pRange = dynamic_cast< ICellRange* >( Range.get() );
329cdf0e10cSrcweir 	if( (pRange == 0) || (pRange->getTable().get() != this) )
330cdf0e10cSrcweir 		throw IllegalArgumentException();
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 	TableModelRef xModel( this );
333cdf0e10cSrcweir 	return new CellCursor( xModel, pRange->getLeft(), pRange->getTop(), pRange->getRight(), pRange->getBottom() );
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir // -----------------------------------------------------------------------------
337cdf0e10cSrcweir 
getRowCount()338cdf0e10cSrcweir sal_Int32 SAL_CALL TableModel::getRowCount() throw (RuntimeException)
339cdf0e10cSrcweir {
340cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
341cdf0e10cSrcweir 	return getRowCountImpl();
342cdf0e10cSrcweir }
343cdf0e10cSrcweir 
344cdf0e10cSrcweir // -----------------------------------------------------------------------------
345cdf0e10cSrcweir 
getColumnCount()346cdf0e10cSrcweir sal_Int32 SAL_CALL TableModel::getColumnCount() throw (RuntimeException)
347cdf0e10cSrcweir {
348cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
349cdf0e10cSrcweir 	return getColumnCountImpl();
350cdf0e10cSrcweir }
351cdf0e10cSrcweir 
352cdf0e10cSrcweir // -----------------------------------------------------------------------------
353cdf0e10cSrcweir // XComponent
354cdf0e10cSrcweir // -----------------------------------------------------------------------------
355cdf0e10cSrcweir 
dispose()356cdf0e10cSrcweir void TableModel::dispose() throw (RuntimeException)
357cdf0e10cSrcweir {
358cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
359cdf0e10cSrcweir 	TableModelBase::dispose();
360cdf0e10cSrcweir }
361cdf0e10cSrcweir 
362cdf0e10cSrcweir // -----------------------------------------------------------------------------
363cdf0e10cSrcweir 
addEventListener(const Reference<XEventListener> & xListener)364cdf0e10cSrcweir void SAL_CALL TableModel::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
365cdf0e10cSrcweir {
366cdf0e10cSrcweir 	TableModelBase::addEventListener( xListener );
367cdf0e10cSrcweir }
368cdf0e10cSrcweir 
369cdf0e10cSrcweir // -----------------------------------------------------------------------------
370cdf0e10cSrcweir 
removeEventListener(const Reference<XEventListener> & xListener)371cdf0e10cSrcweir void SAL_CALL TableModel::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
372cdf0e10cSrcweir {
373cdf0e10cSrcweir 	TableModelBase::removeEventListener( xListener );
374cdf0e10cSrcweir }
375cdf0e10cSrcweir 
376cdf0e10cSrcweir // -----------------------------------------------------------------------------
377cdf0e10cSrcweir // XModifiable
378cdf0e10cSrcweir // -----------------------------------------------------------------------------
379cdf0e10cSrcweir 
isModified()380cdf0e10cSrcweir sal_Bool SAL_CALL TableModel::isModified(  ) throw (RuntimeException)
381cdf0e10cSrcweir {
382cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
383cdf0e10cSrcweir 	return mbModified;
384cdf0e10cSrcweir }
385cdf0e10cSrcweir 
386cdf0e10cSrcweir // -----------------------------------------------------------------------------
387cdf0e10cSrcweir 
setModified(sal_Bool bModified)388cdf0e10cSrcweir void SAL_CALL TableModel::setModified( sal_Bool bModified ) throw (PropertyVetoException, RuntimeException)
389cdf0e10cSrcweir {
390cdf0e10cSrcweir 	{
391cdf0e10cSrcweir 		OGuard aGuard( Application::GetSolarMutex() );
392cdf0e10cSrcweir 		mbModified = bModified;
393cdf0e10cSrcweir 	}
394cdf0e10cSrcweir 	if( bModified )
395cdf0e10cSrcweir 		notifyModification();
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir // -----------------------------------------------------------------------------
399cdf0e10cSrcweir // XModifyBroadcaster
400cdf0e10cSrcweir // -----------------------------------------------------------------------------
401cdf0e10cSrcweir 
addModifyListener(const Reference<XModifyListener> & xListener)402cdf0e10cSrcweir void SAL_CALL TableModel::addModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
403cdf0e10cSrcweir {
404cdf0e10cSrcweir 	rBHelper.addListener( XModifyListener::static_type() , xListener );
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir // -----------------------------------------------------------------------------
408cdf0e10cSrcweir 
removeModifyListener(const Reference<XModifyListener> & xListener)409cdf0e10cSrcweir void SAL_CALL TableModel::removeModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
410cdf0e10cSrcweir {
411cdf0e10cSrcweir 	rBHelper.removeListener( XModifyListener::static_type() , xListener );
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir // -----------------------------------------------------------------------------
415cdf0e10cSrcweir // XColumnRowRange
416cdf0e10cSrcweir // -----------------------------------------------------------------------------
417cdf0e10cSrcweir 
getColumns()418cdf0e10cSrcweir Reference< XTableColumns > SAL_CALL TableModel::getColumns() throw (RuntimeException)
419cdf0e10cSrcweir {
420cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 	if( !mxTableColumns.is() )
423cdf0e10cSrcweir 		mxTableColumns.set( new TableColumns( this ) );
424cdf0e10cSrcweir 	return mxTableColumns.get();
425cdf0e10cSrcweir }
426cdf0e10cSrcweir 
427cdf0e10cSrcweir // -----------------------------------------------------------------------------
428cdf0e10cSrcweir 
getRows()429cdf0e10cSrcweir Reference< XTableRows > SAL_CALL TableModel::getRows() throw (RuntimeException)
430cdf0e10cSrcweir {
431cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 	if( !mxTableRows.is() )
434cdf0e10cSrcweir 		mxTableRows.set( new TableRows( this ) );
435cdf0e10cSrcweir 	return mxTableRows.get();
436cdf0e10cSrcweir }
437cdf0e10cSrcweir 
438cdf0e10cSrcweir // -----------------------------------------------------------------------------
439cdf0e10cSrcweir // XCellRange
440cdf0e10cSrcweir // -----------------------------------------------------------------------------
441cdf0e10cSrcweir 
getCellByPosition(sal_Int32 nColumn,sal_Int32 nRow)442cdf0e10cSrcweir Reference< XCell > SAL_CALL TableModel::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw ( IndexOutOfBoundsException, RuntimeException)
443cdf0e10cSrcweir {
444cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
445cdf0e10cSrcweir 
446cdf0e10cSrcweir 	CellRef xCell( getCell( nColumn, nRow ) );
447cdf0e10cSrcweir 	if( xCell.is() )
448cdf0e10cSrcweir 		return xCell.get();
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 	throw IndexOutOfBoundsException();
451cdf0e10cSrcweir }
452cdf0e10cSrcweir 
453cdf0e10cSrcweir // -----------------------------------------------------------------------------
454cdf0e10cSrcweir 
getCellRangeByPosition(sal_Int32 nLeft,sal_Int32 nTop,sal_Int32 nRight,sal_Int32 nBottom)455cdf0e10cSrcweir Reference< XCellRange > SAL_CALL TableModel::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) throw (IndexOutOfBoundsException, RuntimeException)
456cdf0e10cSrcweir {
457cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
458cdf0e10cSrcweir 
459cdf0e10cSrcweir 	if( (nLeft >= 0) && (nTop >= 0) && (nRight >= nLeft) && (nBottom >= nTop) && (nRight < getColumnCountImpl()) && (nBottom < getRowCountImpl() ) )
460cdf0e10cSrcweir 	{
461cdf0e10cSrcweir 		TableModelRef xModel( this );
462cdf0e10cSrcweir 		return new CellRange( xModel, nLeft, nTop, nRight, nBottom );
463cdf0e10cSrcweir 	}
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 	throw IndexOutOfBoundsException();
466cdf0e10cSrcweir }
467cdf0e10cSrcweir 
468cdf0e10cSrcweir // -----------------------------------------------------------------------------
469cdf0e10cSrcweir 
getCellRangeByName(const OUString &)470cdf0e10cSrcweir Reference< XCellRange > SAL_CALL TableModel::getCellRangeByName( const OUString& /*aRange*/ ) throw (RuntimeException)
471cdf0e10cSrcweir {
472cdf0e10cSrcweir 	return Reference< XCellRange >();
473cdf0e10cSrcweir }
474cdf0e10cSrcweir 
475cdf0e10cSrcweir // -----------------------------------------------------------------------------
476cdf0e10cSrcweir // XPropertySet
477cdf0e10cSrcweir // -----------------------------------------------------------------------------
478cdf0e10cSrcweir 
getPropertySetInfo()479cdf0e10cSrcweir Reference< XPropertySetInfo > SAL_CALL TableModel::getPropertySetInfo(  ) throw (RuntimeException)
480cdf0e10cSrcweir {
481cdf0e10cSrcweir 	Reference< XPropertySetInfo > xInfo;
482cdf0e10cSrcweir 	return xInfo;
483cdf0e10cSrcweir }
484cdf0e10cSrcweir 
485cdf0e10cSrcweir // -----------------------------------------------------------------------------
486cdf0e10cSrcweir 
setPropertyValue(const::rtl::OUString &,const Any &)487cdf0e10cSrcweir void SAL_CALL TableModel::setPropertyValue( const ::rtl::OUString& /*aPropertyName*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
488cdf0e10cSrcweir {
489cdf0e10cSrcweir }
490cdf0e10cSrcweir 
491cdf0e10cSrcweir // -----------------------------------------------------------------------------
492cdf0e10cSrcweir 
getPropertyValue(const OUString &)493cdf0e10cSrcweir Any SAL_CALL TableModel::getPropertyValue( const OUString& /*PropertyName*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
494cdf0e10cSrcweir {
495cdf0e10cSrcweir 	return Any();
496cdf0e10cSrcweir }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir // -----------------------------------------------------------------------------
499cdf0e10cSrcweir 
addPropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)500cdf0e10cSrcweir void SAL_CALL TableModel::addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
501cdf0e10cSrcweir {
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
504cdf0e10cSrcweir // -----------------------------------------------------------------------------
505cdf0e10cSrcweir 
removePropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)506cdf0e10cSrcweir void SAL_CALL TableModel::removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
507cdf0e10cSrcweir {
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir // -----------------------------------------------------------------------------
511cdf0e10cSrcweir 
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)512cdf0e10cSrcweir void SAL_CALL TableModel::addVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
513cdf0e10cSrcweir {
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
516cdf0e10cSrcweir // -----------------------------------------------------------------------------
517cdf0e10cSrcweir 
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)518cdf0e10cSrcweir void SAL_CALL TableModel::removeVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
519cdf0e10cSrcweir {
520cdf0e10cSrcweir }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir // -----------------------------------------------------------------------------
523cdf0e10cSrcweir // XFastPropertySet
524cdf0e10cSrcweir // -----------------------------------------------------------------------------
525cdf0e10cSrcweir 
setFastPropertyValue(::sal_Int32,const Any &)526cdf0e10cSrcweir void SAL_CALL TableModel::setFastPropertyValue( ::sal_Int32 /*nHandle*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
527cdf0e10cSrcweir {
528cdf0e10cSrcweir }
529cdf0e10cSrcweir 
530cdf0e10cSrcweir // -----------------------------------------------------------------------------
531cdf0e10cSrcweir 
getFastPropertyValue(::sal_Int32)532cdf0e10cSrcweir Any SAL_CALL TableModel::getFastPropertyValue( ::sal_Int32 /*nHandle*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
533cdf0e10cSrcweir {
534cdf0e10cSrcweir 	Any aAny;
535cdf0e10cSrcweir 	return aAny;
536cdf0e10cSrcweir }
537cdf0e10cSrcweir 
538cdf0e10cSrcweir // -----------------------------------------------------------------------------
539cdf0e10cSrcweir // internals
540cdf0e10cSrcweir // -----------------------------------------------------------------------------
541cdf0e10cSrcweir 
getRowCountImpl() const542cdf0e10cSrcweir sal_Int32 TableModel::getRowCountImpl() const
543cdf0e10cSrcweir {
544cdf0e10cSrcweir 	return static_cast< sal_Int32 >( maRows.size() );
545cdf0e10cSrcweir }
546cdf0e10cSrcweir 
547cdf0e10cSrcweir // -----------------------------------------------------------------------------
548cdf0e10cSrcweir 
getColumnCountImpl() const549cdf0e10cSrcweir sal_Int32 TableModel::getColumnCountImpl() const
550cdf0e10cSrcweir {
551cdf0e10cSrcweir 	return static_cast< sal_Int32 >( maColumns.size() );
552cdf0e10cSrcweir }
553cdf0e10cSrcweir 
554cdf0e10cSrcweir // -----------------------------------------------------------------------------
555cdf0e10cSrcweir 
disposing()556cdf0e10cSrcweir void TableModel::disposing()
557cdf0e10cSrcweir {
558cdf0e10cSrcweir 	if( !maRows.empty() )
559cdf0e10cSrcweir 	{
560cdf0e10cSrcweir 		RowVector::iterator aIter( maRows.begin() );
561cdf0e10cSrcweir 		while( aIter != maRows.end() )
562cdf0e10cSrcweir 			(*aIter++)->dispose();
563cdf0e10cSrcweir 		RowVector().swap(maRows);
564cdf0e10cSrcweir 	}
565cdf0e10cSrcweir 
566cdf0e10cSrcweir 	if( !maColumns.empty() )
567cdf0e10cSrcweir 	{
568cdf0e10cSrcweir 		ColumnVector::iterator aIter( maColumns.begin() );
569cdf0e10cSrcweir 		while( aIter != maColumns.end() )
570cdf0e10cSrcweir 			(*aIter++)->dispose();
571cdf0e10cSrcweir 		ColumnVector().swap(maColumns);
572cdf0e10cSrcweir 	}
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 	if( mxTableColumns.is() )
575cdf0e10cSrcweir 	{
576cdf0e10cSrcweir 		mxTableColumns->dispose();
577cdf0e10cSrcweir 		mxTableColumns.clear();
578cdf0e10cSrcweir 	}
579cdf0e10cSrcweir 
580cdf0e10cSrcweir 	if( mxTableRows.is() )
581cdf0e10cSrcweir 	{
582cdf0e10cSrcweir 		mxTableRows->dispose();
583cdf0e10cSrcweir 		mxTableRows.clear();
584cdf0e10cSrcweir 	}
585cdf0e10cSrcweir 
586cdf0e10cSrcweir 	mpTableObj = 0;
587cdf0e10cSrcweir }
588cdf0e10cSrcweir 
589cdf0e10cSrcweir // -----------------------------------------------------------------------------
590cdf0e10cSrcweir // XBroadcaster
591cdf0e10cSrcweir // -----------------------------------------------------------------------------
592cdf0e10cSrcweir 
lockBroadcasts()593cdf0e10cSrcweir void TableModel::lockBroadcasts() throw (RuntimeException)
594cdf0e10cSrcweir {
595cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
596cdf0e10cSrcweir 	++mnNotifyLock;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir // -----------------------------------------------------------------------------
599cdf0e10cSrcweir 
unlockBroadcasts()600cdf0e10cSrcweir void TableModel::unlockBroadcasts() throw (RuntimeException)
601cdf0e10cSrcweir {
602cdf0e10cSrcweir 	OGuard aGuard( Application::GetSolarMutex() );
603cdf0e10cSrcweir 	--mnNotifyLock;
604cdf0e10cSrcweir 	if( mnNotifyLock <= 0 )
605cdf0e10cSrcweir 	{
606cdf0e10cSrcweir 		mnNotifyLock = 0;
607cdf0e10cSrcweir 		if( mbNotifyPending )
608cdf0e10cSrcweir 			notifyModification();
609cdf0e10cSrcweir 	}
610cdf0e10cSrcweir }
611cdf0e10cSrcweir 
612cdf0e10cSrcweir // -----------------------------------------------------------------------------
613cdf0e10cSrcweir #ifdef PLEASE_DEBUG_THE_TABLES
614cdf0e10cSrcweir #include <stdio.h>
615cdf0e10cSrcweir #endif
616cdf0e10cSrcweir 
notifyModification()617cdf0e10cSrcweir void TableModel::notifyModification()
618cdf0e10cSrcweir {
619cdf0e10cSrcweir 	::osl::MutexGuard guard( m_aMutex );
620cdf0e10cSrcweir 	if( (mnNotifyLock == 0) && mpTableObj && mpTableObj->GetModel() )
621cdf0e10cSrcweir 	{
622cdf0e10cSrcweir 		mbNotifyPending = false;
623cdf0e10cSrcweir 
624cdf0e10cSrcweir 		::cppu::OInterfaceContainerHelper * pModifyListeners = rBHelper.getContainer( XModifyListener::static_type() );
625cdf0e10cSrcweir 		if( pModifyListeners )
626cdf0e10cSrcweir 		{
627cdf0e10cSrcweir 			EventObject aSource;
628cdf0e10cSrcweir 			aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
629cdf0e10cSrcweir 			pModifyListeners->notifyEach( &XModifyListener::modified, aSource);
630cdf0e10cSrcweir 		}
631cdf0e10cSrcweir 	}
632cdf0e10cSrcweir 	else
633cdf0e10cSrcweir 	{
634cdf0e10cSrcweir 		mbNotifyPending = true;
635cdf0e10cSrcweir 	}
636cdf0e10cSrcweir 
637cdf0e10cSrcweir #ifdef PLEASE_DEBUG_THE_TABLES
638cdf0e10cSrcweir 		FILE* file = fopen( "c:\\table.xml","w" );
639cdf0e10cSrcweir 
640cdf0e10cSrcweir 		const sal_Int32 nColCount = getColumnCountImpl();
641cdf0e10cSrcweir 		const sal_Int32 nRowCount = getRowCountImpl();
642cdf0e10cSrcweir 
643cdf0e10cSrcweir         fprintf( file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\r" );
644cdf0e10cSrcweir         fprintf( file, "<table columns=\"%ld\" rows=\"%ld\" updated=\"%s\">\n\r", nColCount, nRowCount, mbNotifyPending ? "false" : "true");
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 		for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
647cdf0e10cSrcweir 		{
648cdf0e10cSrcweir 			fprintf( file, "<column this=\"%lx\"/>\n\r", maColumns[nCol].get() );
649cdf0e10cSrcweir 		}
650cdf0e10cSrcweir 
651cdf0e10cSrcweir 		// first check merged cells before and inside the removed rows
652cdf0e10cSrcweir 		for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
653cdf0e10cSrcweir 		{
654cdf0e10cSrcweir 			fprintf( file, "<row this=\"%lx\">\n\r", maRows[nRow].get() );
655cdf0e10cSrcweir 			for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
656cdf0e10cSrcweir 			{
657cdf0e10cSrcweir 				CellRef xCell( getCell( nCol, nRow ) );
658cdf0e10cSrcweir 				fprintf( file, "<cell this=\"%lx\"", xCell.get() );
659cdf0e10cSrcweir 
660cdf0e10cSrcweir 				sal_Int32 nRowSpan = xCell->getRowSpan();
661cdf0e10cSrcweir 				sal_Int32 nColSpan = xCell->getColumnSpan();
662cdf0e10cSrcweir 				sal_Bool bMerged = xCell->isMerged();
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 				if( nColSpan != 1 )
665cdf0e10cSrcweir 					fprintf( file, " column-span=\"%ld\"", nColSpan );
666cdf0e10cSrcweir 				if( nRowSpan != 1 )
667cdf0e10cSrcweir 					fprintf( file, " row-span=\"%ld\"", nRowSpan );
668cdf0e10cSrcweir 
669cdf0e10cSrcweir 				if( bMerged )
670cdf0e10cSrcweir 					fprintf( file, " merged=\"true\"" );
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 				fprintf( file, "/>" );
673cdf0e10cSrcweir 			}
674cdf0e10cSrcweir 			fprintf( file, "\n\r</row>\n\r" );
675cdf0e10cSrcweir 		}
676cdf0e10cSrcweir 
677cdf0e10cSrcweir 		fprintf( file, "</table>\n\r" );
678cdf0e10cSrcweir 		fclose( file );
679cdf0e10cSrcweir #endif
680cdf0e10cSrcweir }
681cdf0e10cSrcweir 
682cdf0e10cSrcweir // -----------------------------------------------------------------------------
683cdf0e10cSrcweir 
getCell(sal_Int32 nCol,sal_Int32 nRow) const684cdf0e10cSrcweir CellRef TableModel::getCell( sal_Int32 nCol, sal_Int32 nRow ) const
685cdf0e10cSrcweir {
686cdf0e10cSrcweir 	if( ((nRow >= 0) && (nRow < getRowCountImpl())) && (nCol >= 0) && (nCol < getColumnCountImpl()) )
687cdf0e10cSrcweir 	{
688cdf0e10cSrcweir 		return maRows[nRow]->maCells[nCol];
689cdf0e10cSrcweir 	}
690cdf0e10cSrcweir 	else
691cdf0e10cSrcweir 	{
692cdf0e10cSrcweir 		CellRef xRet;
693cdf0e10cSrcweir 		return xRet;
694cdf0e10cSrcweir 	}
695cdf0e10cSrcweir }
696cdf0e10cSrcweir 
697cdf0e10cSrcweir // -----------------------------------------------------------------------------
698cdf0e10cSrcweir /*
699cdf0e10cSrcweir bool TableModel::getCellPos( const CellRef& xCell, ::sal_Int32& rnCol, ::sal_Int32& rnRow ) const
700cdf0e10cSrcweir {
701cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
702cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
703cdf0e10cSrcweir 	for( rnRow = 0; rnRow < nRowCount; rnRow++ )
704cdf0e10cSrcweir 	{
705cdf0e10cSrcweir 		for( rnCol = 0; rnCol < nColCount; rnCol++ )
706cdf0e10cSrcweir 		{
707cdf0e10cSrcweir 			if( maRows[rnRow]->maCells[rnCol] == xCell )
708cdf0e10cSrcweir 			{
709cdf0e10cSrcweir 				return true;
710cdf0e10cSrcweir 			}
711cdf0e10cSrcweir 		}
712cdf0e10cSrcweir 	}
713cdf0e10cSrcweir 	return false;
714cdf0e10cSrcweir }
715cdf0e10cSrcweir */
716cdf0e10cSrcweir 
717cdf0e10cSrcweir // -----------------------------------------------------------------------------
718cdf0e10cSrcweir 
createCell()719cdf0e10cSrcweir CellRef TableModel::createCell()
720cdf0e10cSrcweir {
721cdf0e10cSrcweir 	CellRef xCell;
722cdf0e10cSrcweir 	if( mpTableObj )
723cdf0e10cSrcweir 		mpTableObj->createCell( xCell );
724cdf0e10cSrcweir 	return xCell;
725cdf0e10cSrcweir }
726cdf0e10cSrcweir 
727cdf0e10cSrcweir // -----------------------------------------------------------------------------
728cdf0e10cSrcweir 
insertColumns(sal_Int32 nIndex,sal_Int32 nCount)729cdf0e10cSrcweir void TableModel::insertColumns( sal_Int32 nIndex, sal_Int32 nCount )
730cdf0e10cSrcweir {
731cdf0e10cSrcweir 	if( nCount && mpTableObj )
732cdf0e10cSrcweir 	{
733cdf0e10cSrcweir 		try
734cdf0e10cSrcweir 		{
735cdf0e10cSrcweir 			SdrModel* pModel = mpTableObj->GetModel();
736cdf0e10cSrcweir 
737cdf0e10cSrcweir 			TableModelNotifyGuard aGuard( this );
738cdf0e10cSrcweir 			nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
739cdf0e10cSrcweir 
740cdf0e10cSrcweir 			sal_Int32 nRows = getRowCountImpl();
741cdf0e10cSrcweir 			while( nRows-- )
742cdf0e10cSrcweir 				maRows[nRows]->insertColumns( nIndex, nCount );
743cdf0e10cSrcweir 
744cdf0e10cSrcweir 			ColumnVector aNewColumns(nCount);
745cdf0e10cSrcweir 			for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
746cdf0e10cSrcweir 			{
747cdf0e10cSrcweir 				TableColumnRef xNewCol( new TableColumn( this, nIndex+nOffset ) );
748cdf0e10cSrcweir 				maColumns[nIndex+nOffset] = xNewCol;
749cdf0e10cSrcweir 				aNewColumns[nOffset] = xNewCol;
750cdf0e10cSrcweir 			}
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 			const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
753cdf0e10cSrcweir 			if( bUndo )
754cdf0e10cSrcweir 			{
755cdf0e10cSrcweir 				pModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
756cdf0e10cSrcweir 				pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
757cdf0e10cSrcweir 
758cdf0e10cSrcweir 				TableModelRef xThis( this );
759cdf0e10cSrcweir 
760cdf0e10cSrcweir 				nRows = getRowCountImpl();
761cdf0e10cSrcweir 				CellVector aNewCells( nCount * nRows );
762cdf0e10cSrcweir 				CellVector::iterator aCellIter( aNewCells.begin() );
763cdf0e10cSrcweir 
764cdf0e10cSrcweir 				nRows = getRowCountImpl();
765cdf0e10cSrcweir 				for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
766cdf0e10cSrcweir 				{
767cdf0e10cSrcweir 					for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
768cdf0e10cSrcweir 						(*aCellIter++) = getCell( nIndex + nOffset, nRow );
769cdf0e10cSrcweir 				}
770cdf0e10cSrcweir 
771cdf0e10cSrcweir 				pModel->AddUndo( new InsertColUndo( xThis, nIndex, aNewColumns, aNewCells ) );
772cdf0e10cSrcweir 			}
773cdf0e10cSrcweir 
774cdf0e10cSrcweir 			const sal_Int32 nRowCount = getRowCountImpl();
775cdf0e10cSrcweir 			// check if cells merge over new columns
776cdf0e10cSrcweir 			for( sal_Int32 nCol = 0; nCol < nIndex; ++nCol )
777cdf0e10cSrcweir 			{
778cdf0e10cSrcweir 				for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
779cdf0e10cSrcweir 				{
780cdf0e10cSrcweir 					CellRef xCell( getCell( nCol, nRow ) );
781cdf0e10cSrcweir 					sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
782cdf0e10cSrcweir 					if( (nColSpan != 1) && ((nColSpan + nCol ) > nIndex) )
783cdf0e10cSrcweir 					{
784cdf0e10cSrcweir 						// cell merges over newly created columns, so add the new columns to the merged cell
785cdf0e10cSrcweir 						const sal_Int32 nRowSpan = xCell->getRowSpan();
786cdf0e10cSrcweir 						nColSpan += nCount;
787cdf0e10cSrcweir                         merge( nCol, nRow, nColSpan, nRowSpan );
788cdf0e10cSrcweir 					}
789cdf0e10cSrcweir 				}
790cdf0e10cSrcweir 			}
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 			if( bUndo )
793cdf0e10cSrcweir 				pModel->EndUndo();
794cdf0e10cSrcweir 
795cdf0e10cSrcweir 			if( pModel )
796cdf0e10cSrcweir 			    pModel->SetChanged();
797cdf0e10cSrcweir 
798cdf0e10cSrcweir 		}
799cdf0e10cSrcweir 		catch( Exception& )
800cdf0e10cSrcweir 		{
801cdf0e10cSrcweir 			DBG_ERROR("sdr::table::TableModel::insertColumns(), exception caught!");
802cdf0e10cSrcweir 		}
803cdf0e10cSrcweir         updateColumns();
804cdf0e10cSrcweir 		setModified(sal_True);
805cdf0e10cSrcweir 	}
806cdf0e10cSrcweir }
807cdf0e10cSrcweir 
808cdf0e10cSrcweir // -----------------------------------------------------------------------------
809cdf0e10cSrcweir 
removeColumns(sal_Int32 nIndex,sal_Int32 nCount)810cdf0e10cSrcweir void TableModel::removeColumns( sal_Int32 nIndex, sal_Int32 nCount )
811cdf0e10cSrcweir {
812cdf0e10cSrcweir 	sal_Int32 nColCount = getColumnCountImpl();
813cdf0e10cSrcweir 
814cdf0e10cSrcweir 	if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nColCount) )
815cdf0e10cSrcweir 	{
816cdf0e10cSrcweir 		try
817cdf0e10cSrcweir 		{
818cdf0e10cSrcweir 			TableModelNotifyGuard aGuard( this );
819cdf0e10cSrcweir 
820cdf0e10cSrcweir 			// clip removed columns to columns actually avalaible
821cdf0e10cSrcweir 			if( (nIndex + nCount) > nColCount )
822cdf0e10cSrcweir 				nCount = nColCount - nIndex;
823cdf0e10cSrcweir 
824cdf0e10cSrcweir 			sal_Int32 nRows = getRowCountImpl();
825cdf0e10cSrcweir 
826cdf0e10cSrcweir 			SdrModel* pModel = mpTableObj->GetModel();
827cdf0e10cSrcweir 
828cdf0e10cSrcweir 			const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
829cdf0e10cSrcweir 			if( bUndo  )
830cdf0e10cSrcweir 			{
831cdf0e10cSrcweir 				pModel->BegUndo( ImpGetResStr(STR_UNDO_COL_DELETE) );
832cdf0e10cSrcweir 				pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
833cdf0e10cSrcweir 
834cdf0e10cSrcweir 				TableModelRef xThis( this );
835cdf0e10cSrcweir 				ColumnVector aRemovedCols( nCount );
836cdf0e10cSrcweir 				sal_Int32 nOffset;
837cdf0e10cSrcweir 				for( nOffset = 0; nOffset < nCount; ++nOffset )
838cdf0e10cSrcweir 				{
839cdf0e10cSrcweir 					aRemovedCols[nOffset] = maColumns[nIndex+nOffset];
840cdf0e10cSrcweir 				}
841cdf0e10cSrcweir 
842cdf0e10cSrcweir 				CellVector aRemovedCells( nCount * nRows );
843cdf0e10cSrcweir 				CellVector::iterator aCellIter( aRemovedCells.begin() );
844cdf0e10cSrcweir 				for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
845cdf0e10cSrcweir 				{
846cdf0e10cSrcweir 					for( nOffset = 0; nOffset < nCount; ++nOffset )
847cdf0e10cSrcweir 						(*aCellIter++) = getCell( nIndex + nOffset, nRow );
848cdf0e10cSrcweir 				}
849cdf0e10cSrcweir 
850cdf0e10cSrcweir 				pModel->AddUndo( new RemoveColUndo( xThis, nIndex, aRemovedCols, aRemovedCells ) );
851cdf0e10cSrcweir 			}
852cdf0e10cSrcweir 
853cdf0e10cSrcweir 			// only rows before and inside the removed rows are considered
854cdf0e10cSrcweir 			nColCount = nIndex + nCount + 1;
855cdf0e10cSrcweir 
856cdf0e10cSrcweir 			const sal_Int32 nRowCount = getRowCountImpl();
857cdf0e10cSrcweir 
858cdf0e10cSrcweir 			// first check merged cells before and inside the removed rows
859cdf0e10cSrcweir 			for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
860cdf0e10cSrcweir 			{
861cdf0e10cSrcweir 				for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
862cdf0e10cSrcweir 				{
863cdf0e10cSrcweir 					CellRef xCell( getCell( nCol, nRow ) );
864cdf0e10cSrcweir 					sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
865cdf0e10cSrcweir 					if( nColSpan <= 1 )
866cdf0e10cSrcweir 						continue;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 					if( nCol >= nIndex )
869cdf0e10cSrcweir 					{
870cdf0e10cSrcweir 						// current cell is inside the removed columns
871cdf0e10cSrcweir 						if( (nCol + nColSpan) > ( nIndex + nCount ) )
872cdf0e10cSrcweir 						{
873cdf0e10cSrcweir 							// current cells merges with columns after the removed columns
874cdf0e10cSrcweir 							const sal_Int32 nRemove = nCount - nCol + nIndex;
875cdf0e10cSrcweir 
876cdf0e10cSrcweir 							CellRef xTargetCell( getCell( nIndex + nCount, nRow ) );
877cdf0e10cSrcweir 							if( xTargetCell.is() )
878cdf0e10cSrcweir 							{
879cdf0e10cSrcweir 								if( bUndo )
880cdf0e10cSrcweir 									xTargetCell->AddUndo();
881cdf0e10cSrcweir 								xTargetCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
882cdf0e10cSrcweir 								xTargetCell->replaceContentAndFormating( xCell );
883cdf0e10cSrcweir 							}
884cdf0e10cSrcweir 						}
885cdf0e10cSrcweir 					}
886cdf0e10cSrcweir 					else if( nColSpan > (nIndex - nCol) )
887cdf0e10cSrcweir 					{
888cdf0e10cSrcweir 						// current cells spans inside the removed columns, so adjust
889cdf0e10cSrcweir 						const sal_Int32 nRemove = ::std::min( nCount, nCol + nColSpan - nIndex );
890cdf0e10cSrcweir 						if( bUndo )
891cdf0e10cSrcweir 							xCell->AddUndo();
892cdf0e10cSrcweir 						xCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
893cdf0e10cSrcweir 					}
894cdf0e10cSrcweir 				}
895cdf0e10cSrcweir 			}
896cdf0e10cSrcweir 
897cdf0e10cSrcweir 			// now remove the columns
898cdf0e10cSrcweir 			remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
899cdf0e10cSrcweir 			while( nRows-- )
900cdf0e10cSrcweir 				maRows[nRows]->removeColumns( nIndex, nCount );
901cdf0e10cSrcweir 
902cdf0e10cSrcweir 			if( bUndo )
903cdf0e10cSrcweir 				pModel->EndUndo();
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 			if( pModel )
906cdf0e10cSrcweir                 pModel->SetChanged();
907cdf0e10cSrcweir 		}
908cdf0e10cSrcweir 		catch( Exception& )
909cdf0e10cSrcweir 		{
910cdf0e10cSrcweir 			DBG_ERROR("sdr::table::TableModel::removeColumns(), exception caught!");
911cdf0e10cSrcweir 		}
912cdf0e10cSrcweir 
913cdf0e10cSrcweir         updateColumns();
914cdf0e10cSrcweir 		setModified(sal_True);
915cdf0e10cSrcweir 	}
916cdf0e10cSrcweir }
917cdf0e10cSrcweir 
918cdf0e10cSrcweir // -----------------------------------------------------------------------------
919cdf0e10cSrcweir 
insertRows(sal_Int32 nIndex,sal_Int32 nCount)920cdf0e10cSrcweir void TableModel::insertRows( sal_Int32 nIndex, sal_Int32 nCount )
921cdf0e10cSrcweir {
922cdf0e10cSrcweir 	if( nCount && mpTableObj )
923cdf0e10cSrcweir 	{
924cdf0e10cSrcweir     	SdrModel* pModel = mpTableObj->GetModel();
925cdf0e10cSrcweir 		const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
926cdf0e10cSrcweir 		try
927cdf0e10cSrcweir 		{
928cdf0e10cSrcweir 			TableModelNotifyGuard aGuard( this );
929cdf0e10cSrcweir 
930cdf0e10cSrcweir 			nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
931cdf0e10cSrcweir 
932cdf0e10cSrcweir 			RowVector aNewRows(nCount);
933cdf0e10cSrcweir 			const sal_Int32 nColCount = getColumnCountImpl();
934cdf0e10cSrcweir 			for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
935cdf0e10cSrcweir 			{
936cdf0e10cSrcweir 				TableRowRef xNewRow( new TableRow( this, nIndex+nOffset, nColCount ) );
937cdf0e10cSrcweir 				maRows[nIndex+nOffset] = xNewRow;
938cdf0e10cSrcweir 				aNewRows[nOffset] = xNewRow;
939cdf0e10cSrcweir 			}
940cdf0e10cSrcweir 
941cdf0e10cSrcweir 			if( bUndo )
942cdf0e10cSrcweir 			{
943cdf0e10cSrcweir 				pModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW) );
944cdf0e10cSrcweir 				pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
945cdf0e10cSrcweir 				TableModelRef xThis( this );
946cdf0e10cSrcweir 				pModel->AddUndo( new InsertRowUndo( xThis, nIndex, aNewRows ) );
947cdf0e10cSrcweir 			}
948cdf0e10cSrcweir 
949cdf0e10cSrcweir 			// check if cells merge over new columns
950cdf0e10cSrcweir 			for( sal_Int32 nRow = 0; nRow < nIndex; ++nRow )
951cdf0e10cSrcweir 			{
952cdf0e10cSrcweir 				for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
953cdf0e10cSrcweir 				{
954cdf0e10cSrcweir 					CellRef xCell( getCell( nCol, nRow ) );
955cdf0e10cSrcweir 					sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
956cdf0e10cSrcweir 					if( (nRowSpan > 1) && ((nRowSpan + nRow) > nIndex) )
957cdf0e10cSrcweir 					{
958cdf0e10cSrcweir 						// cell merges over newly created columns, so add the new columns to the merged cell
959cdf0e10cSrcweir 						const sal_Int32 nColSpan = xCell->getColumnSpan();
960cdf0e10cSrcweir 						nRowSpan += nCount;
961cdf0e10cSrcweir                         merge( nCol, nRow, nColSpan, nRowSpan );
962cdf0e10cSrcweir 					}
963cdf0e10cSrcweir 				}
964cdf0e10cSrcweir 			}
965cdf0e10cSrcweir 		}
966cdf0e10cSrcweir 		catch( Exception& )
967cdf0e10cSrcweir 		{
968cdf0e10cSrcweir 			DBG_ERROR("sdr::table::TableModel::insertRows(), exception caught!");
969cdf0e10cSrcweir 		}
970cdf0e10cSrcweir 		if( bUndo )
971cdf0e10cSrcweir 			pModel->EndUndo();
972cdf0e10cSrcweir 
973cdf0e10cSrcweir 		if( pModel )
974cdf0e10cSrcweir 			pModel->SetChanged();
975cdf0e10cSrcweir 
976cdf0e10cSrcweir         updateRows();
977cdf0e10cSrcweir 		setModified(sal_True);
978cdf0e10cSrcweir 	}
979cdf0e10cSrcweir }
980cdf0e10cSrcweir 
981cdf0e10cSrcweir // -----------------------------------------------------------------------------
982cdf0e10cSrcweir 
removeRows(sal_Int32 nIndex,sal_Int32 nCount)983cdf0e10cSrcweir void TableModel::removeRows( sal_Int32 nIndex, sal_Int32 nCount )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir 	sal_Int32 nRowCount = getRowCountImpl();
986cdf0e10cSrcweir 
987cdf0e10cSrcweir 	if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nRowCount) )
988cdf0e10cSrcweir 	{
989cdf0e10cSrcweir 		SdrModel* pModel = mpTableObj->GetModel();
990cdf0e10cSrcweir 		const bool bUndo = pModel && mpTableObj->IsInserted()&& pModel->IsUndoEnabled();
991cdf0e10cSrcweir 
992cdf0e10cSrcweir 		try
993cdf0e10cSrcweir 		{
994cdf0e10cSrcweir 			TableModelNotifyGuard aGuard( this );
995cdf0e10cSrcweir 
996cdf0e10cSrcweir 			// clip removed rows to rows actually avalaible
997cdf0e10cSrcweir 			if( (nIndex + nCount) > nRowCount )
998cdf0e10cSrcweir 				nCount = nRowCount - nIndex;
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir 			if( bUndo )
1001cdf0e10cSrcweir 			{
1002cdf0e10cSrcweir 				pModel->BegUndo( ImpGetResStr(STR_UNDO_ROW_DELETE) );
1003cdf0e10cSrcweir 				pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir 				TableModelRef xThis( this );
1006cdf0e10cSrcweir 
1007cdf0e10cSrcweir 				RowVector aRemovedRows( nCount );
1008cdf0e10cSrcweir 				for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
1009cdf0e10cSrcweir 					aRemovedRows[nOffset] = maRows[nIndex+nOffset];
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir 				pModel->AddUndo( new RemoveRowUndo( xThis, nIndex, aRemovedRows ) );
1012cdf0e10cSrcweir 			}
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir 			// only rows before and inside the removed rows are considered
1015cdf0e10cSrcweir 			nRowCount = nIndex + nCount + 1;
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir 			const sal_Int32 nColCount = getColumnCountImpl();
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir 			// first check merged cells before and inside the removed rows
1020cdf0e10cSrcweir 			for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
1021cdf0e10cSrcweir 			{
1022cdf0e10cSrcweir 				for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
1023cdf0e10cSrcweir 				{
1024cdf0e10cSrcweir 					CellRef xCell( getCell( nCol, nRow ) );
1025cdf0e10cSrcweir 					sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
1026cdf0e10cSrcweir 					if( nRowSpan <= 1 )
1027cdf0e10cSrcweir 						continue;
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir 					if( nRow >= nIndex )
1030cdf0e10cSrcweir 					{
1031cdf0e10cSrcweir 						// current cell is inside the removed rows
1032cdf0e10cSrcweir 						if( (nRow + nRowSpan) > (nIndex + nCount) )
1033cdf0e10cSrcweir 						{
1034cdf0e10cSrcweir 							// current cells merges with rows after the removed rows
1035cdf0e10cSrcweir 							const sal_Int32 nRemove = nCount - nRow + nIndex;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir 							CellRef xTargetCell( getCell( nCol, nIndex + nCount ) );
1038cdf0e10cSrcweir 							if( xTargetCell.is() )
1039cdf0e10cSrcweir 							{
1040cdf0e10cSrcweir 								if( bUndo )
1041cdf0e10cSrcweir 									xTargetCell->AddUndo();
1042cdf0e10cSrcweir 								xTargetCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
1043cdf0e10cSrcweir 								xTargetCell->replaceContentAndFormating( xCell );
1044cdf0e10cSrcweir 							}
1045cdf0e10cSrcweir 						}
1046cdf0e10cSrcweir 					}
1047cdf0e10cSrcweir 					else if( nRowSpan > (nIndex - nRow) )
1048cdf0e10cSrcweir 					{
1049cdf0e10cSrcweir 						// current cells spans inside the removed rows, so adjust
1050cdf0e10cSrcweir 						const sal_Int32 nRemove = ::std::min( nCount, nRow + nRowSpan - nIndex );
1051cdf0e10cSrcweir 						if( bUndo )
1052cdf0e10cSrcweir 							xCell->AddUndo();
1053cdf0e10cSrcweir 						xCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
1054cdf0e10cSrcweir 					}
1055cdf0e10cSrcweir 				}
1056cdf0e10cSrcweir 			}
1057cdf0e10cSrcweir 
1058cdf0e10cSrcweir 			// now remove the rows
1059cdf0e10cSrcweir 			remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
1060cdf0e10cSrcweir 
1061cdf0e10cSrcweir 			if( bUndo )
1062cdf0e10cSrcweir 				pModel->EndUndo();
1063cdf0e10cSrcweir 
1064cdf0e10cSrcweir 			if( pModel )
1065cdf0e10cSrcweir                 pModel->SetChanged();
1066cdf0e10cSrcweir 		}
1067cdf0e10cSrcweir 		catch( Exception& )
1068cdf0e10cSrcweir 		{
1069cdf0e10cSrcweir 			DBG_ERROR("sdr::table::TableModel::removeRows(), exception caught!");
1070cdf0e10cSrcweir 		}
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir         updateRows();
1073cdf0e10cSrcweir 		setModified(sal_True);
1074cdf0e10cSrcweir 	}
1075cdf0e10cSrcweir }
1076cdf0e10cSrcweir 
1077cdf0e10cSrcweir // -----------------------------------------------------------------------------
1078cdf0e10cSrcweir 
getRow(sal_Int32 nRow) const1079cdf0e10cSrcweir TableRowRef TableModel::getRow( sal_Int32 nRow ) const throw (IndexOutOfBoundsException)
1080cdf0e10cSrcweir {
1081cdf0e10cSrcweir 	if( (nRow >= 0) && (nRow < getRowCountImpl()) )
1082cdf0e10cSrcweir 		return maRows[nRow];
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir 	throw IndexOutOfBoundsException();
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir // -----------------------------------------------------------------------------
1088cdf0e10cSrcweir 
getColumn(sal_Int32 nColumn) const1089cdf0e10cSrcweir TableColumnRef TableModel::getColumn( sal_Int32 nColumn ) const throw (IndexOutOfBoundsException)
1090cdf0e10cSrcweir {
1091cdf0e10cSrcweir 	if( (nColumn >= 0) && (nColumn < getColumnCountImpl()) )
1092cdf0e10cSrcweir 		return maColumns[nColumn];
1093cdf0e10cSrcweir 
1094cdf0e10cSrcweir 	throw IndexOutOfBoundsException();
1095cdf0e10cSrcweir }
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir // -----------------------------------------------------------------------------
1098cdf0e10cSrcweir 
1099cdf0e10cSrcweir /** deletes rows and columns that are completly merged. Must be called between BegUndo/EndUndo! */
optimize()1100cdf0e10cSrcweir void TableModel::optimize()
1101cdf0e10cSrcweir {
1102cdf0e10cSrcweir 	TableModelNotifyGuard aGuard( this );
1103cdf0e10cSrcweir 
1104cdf0e10cSrcweir 	bool bWasModified = false;
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir 	if( !maRows.empty() && !maColumns.empty() )
1107cdf0e10cSrcweir 	{
1108cdf0e10cSrcweir 		sal_Int32 nCol = getColumnCountImpl() - 1;
1109cdf0e10cSrcweir 		while( nCol > 0 )
1110cdf0e10cSrcweir 		{
1111cdf0e10cSrcweir 			bool bEmpty = true;
1112cdf0e10cSrcweir 			for( sal_Int32 nRow = 0; (nRow < getRowCountImpl()) && bEmpty; nRow++ )
1113cdf0e10cSrcweir 			{
1114cdf0e10cSrcweir 				Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
1115cdf0e10cSrcweir 				if( xCell.is() && !xCell->isMerged() )
1116cdf0e10cSrcweir 					bEmpty = false;
1117cdf0e10cSrcweir 			}
1118cdf0e10cSrcweir 
1119cdf0e10cSrcweir 			if( bEmpty )
1120cdf0e10cSrcweir 			{
1121cdf0e10cSrcweir 				if( nCol > 0 ) try
1122cdf0e10cSrcweir 				{
1123cdf0e10cSrcweir 					const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
1124cdf0e10cSrcweir 					sal_Int32 nWidth1 = 0, nWidth2 = 0;
1125cdf0e10cSrcweir 					Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maColumns[nCol].get() ), UNO_QUERY_THROW );
1126cdf0e10cSrcweir 					Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maColumns[nCol-1].get() ), UNO_QUERY_THROW );
1127cdf0e10cSrcweir 					xSet1->getPropertyValue( sWidth ) >>= nWidth1;
1128cdf0e10cSrcweir 					xSet2->getPropertyValue( sWidth ) >>= nWidth2;
1129cdf0e10cSrcweir 					nWidth1 += nWidth2;
1130cdf0e10cSrcweir 					xSet2->setPropertyValue( sWidth, Any( nWidth1 ) );
1131cdf0e10cSrcweir 				}
1132cdf0e10cSrcweir 				catch( Exception& e )
1133cdf0e10cSrcweir 				{
1134cdf0e10cSrcweir 					(void)e;
1135cdf0e10cSrcweir 					DBG_ERROR("svx::TableModel::optimize(), exception caught!");
1136cdf0e10cSrcweir 				}
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir 				removeColumns( nCol, 1 );
1139cdf0e10cSrcweir 				bWasModified = true;
1140cdf0e10cSrcweir 			}
1141cdf0e10cSrcweir 
1142cdf0e10cSrcweir 			nCol--;
1143cdf0e10cSrcweir 		}
1144cdf0e10cSrcweir 
1145cdf0e10cSrcweir 		sal_Int32 nRow = getRowCountImpl() - 1;
1146cdf0e10cSrcweir 		while( nRow > 0 )
1147cdf0e10cSrcweir 		{
1148cdf0e10cSrcweir 			bool bEmpty = true;
1149cdf0e10cSrcweir 			for( nCol = 0; (nCol < getColumnCountImpl()) && bEmpty; nCol++ )
1150cdf0e10cSrcweir 			{
1151cdf0e10cSrcweir 				Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
1152cdf0e10cSrcweir 				if( xCell.is() && !xCell->isMerged() )
1153cdf0e10cSrcweir 					bEmpty = false;
1154cdf0e10cSrcweir 			}
1155cdf0e10cSrcweir 
1156cdf0e10cSrcweir 			if( bEmpty )
1157cdf0e10cSrcweir 			{
1158cdf0e10cSrcweir 				if( nRow > 0 ) try
1159cdf0e10cSrcweir 				{
1160cdf0e10cSrcweir 					const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM("Height") );
1161cdf0e10cSrcweir 					sal_Int32 nHeight1 = 0, nHeight2 = 0;
1162cdf0e10cSrcweir 					Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maRows[nRow].get() ), UNO_QUERY_THROW );
1163cdf0e10cSrcweir 					Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maRows[nRow-1].get() ), UNO_QUERY_THROW );
1164cdf0e10cSrcweir 					xSet1->getPropertyValue( sHeight ) >>= nHeight1;
1165cdf0e10cSrcweir 					xSet2->getPropertyValue( sHeight ) >>= nHeight2;
1166cdf0e10cSrcweir 					nHeight1 += nHeight2;
1167cdf0e10cSrcweir 					xSet2->setPropertyValue( sHeight, Any( nHeight1 ) );
1168cdf0e10cSrcweir 				}
1169cdf0e10cSrcweir 				catch( Exception& e )
1170cdf0e10cSrcweir 				{
1171cdf0e10cSrcweir 					(void)e;
1172cdf0e10cSrcweir 					DBG_ERROR("svx::TableModel::optimize(), exception caught!");
1173cdf0e10cSrcweir 				}
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir 				removeRows( nRow, 1 );
1176cdf0e10cSrcweir 				bWasModified = true;
1177cdf0e10cSrcweir 			}
1178cdf0e10cSrcweir 
1179cdf0e10cSrcweir 			nRow--;
1180cdf0e10cSrcweir 		}
1181cdf0e10cSrcweir 	}
1182cdf0e10cSrcweir 	if( bWasModified )
1183cdf0e10cSrcweir 		setModified(sal_True);
1184cdf0e10cSrcweir }
1185cdf0e10cSrcweir 
1186cdf0e10cSrcweir // -----------------------------------------------------------------------------
1187cdf0e10cSrcweir 
merge(sal_Int32 nCol,sal_Int32 nRow,sal_Int32 nColSpan,sal_Int32 nRowSpan)1188cdf0e10cSrcweir void TableModel::merge( sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
1189cdf0e10cSrcweir {
1190cdf0e10cSrcweir 	SdrModel* pModel = mpTableObj->GetModel();
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir     const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir 	const sal_Int32 nLastRow = nRow + nRowSpan;
1195cdf0e10cSrcweir 	const sal_Int32 nLastCol = nCol + nColSpan;
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir     if( (nLastRow > getRowCount()) || (nLastCol > getRowCount() ) )
1198cdf0e10cSrcweir     {
1199cdf0e10cSrcweir         DBG_ERROR("TableModel::merge(), merge beyound the table!");
1200cdf0e10cSrcweir     }
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir 	// merge first cell
1203cdf0e10cSrcweir 	CellRef xOriginCell( dynamic_cast< Cell* >( getCellByPosition( nCol, nRow ).get() ) );
1204cdf0e10cSrcweir 	if( xOriginCell.is() )
1205cdf0e10cSrcweir 	{
1206cdf0e10cSrcweir 	    if( bUndo )
1207cdf0e10cSrcweir 		    xOriginCell->AddUndo();
1208cdf0e10cSrcweir 		xOriginCell->merge( nColSpan, nRowSpan );
1209cdf0e10cSrcweir 	}
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir 	sal_Int32 nTempCol = nCol + 1;
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir 	// merge remaining cells
1214cdf0e10cSrcweir 	for( ; nRow < nLastRow; nRow++ )
1215cdf0e10cSrcweir 	{
1216cdf0e10cSrcweir 		for( ; nTempCol < nLastCol; nTempCol++ )
1217cdf0e10cSrcweir 		{
1218cdf0e10cSrcweir 			CellRef xCell( dynamic_cast< Cell* >( getCellByPosition( nTempCol, nRow ).get() ) );
1219cdf0e10cSrcweir 			if( xCell.is() && !xCell->isMerged() )
1220cdf0e10cSrcweir 			{
1221cdf0e10cSrcweir 			    if( bUndo )
1222cdf0e10cSrcweir 				    xCell->AddUndo();
1223cdf0e10cSrcweir 				xCell->setMerged();
1224cdf0e10cSrcweir 				xOriginCell->mergeContent( xCell );
1225cdf0e10cSrcweir 			}
1226cdf0e10cSrcweir 		}
1227cdf0e10cSrcweir 		nTempCol = nCol;
1228cdf0e10cSrcweir 	}
1229cdf0e10cSrcweir }
1230cdf0e10cSrcweir 
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir // -----------------------------------------------------------------------------
1233cdf0e10cSrcweir 
updateRows()1234cdf0e10cSrcweir void TableModel::updateRows()
1235cdf0e10cSrcweir {
1236cdf0e10cSrcweir     sal_Int32 nRow = 0;
1237cdf0e10cSrcweir     RowVector::iterator iter = maRows.begin();
1238cdf0e10cSrcweir     while( iter != maRows.end() )
1239cdf0e10cSrcweir     {
1240cdf0e10cSrcweir         (*iter++)->mnRow = nRow++;
1241cdf0e10cSrcweir     }
1242cdf0e10cSrcweir }
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir // -----------------------------------------------------------------------------
1245cdf0e10cSrcweir 
updateColumns()1246cdf0e10cSrcweir void TableModel::updateColumns()
1247cdf0e10cSrcweir {
1248cdf0e10cSrcweir     sal_Int32 nColumn = 0;
1249cdf0e10cSrcweir     ColumnVector::iterator iter = maColumns.begin();
1250cdf0e10cSrcweir     while( iter != maColumns.end() )
1251cdf0e10cSrcweir     {
1252cdf0e10cSrcweir         (*iter++)->mnColumn = nColumn++;
1253cdf0e10cSrcweir     }
1254cdf0e10cSrcweir }
1255cdf0e10cSrcweir 
1256cdf0e10cSrcweir // -----------------------------------------------------------------------------
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir } }
1259