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