xref: /AOO41X/main/svx/source/table/tablelayouter.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 #include <com/sun/star/awt/XLayoutConstrains.hpp>
33*cdf0e10cSrcweir #include <boost/bind.hpp>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include "cell.hxx"
36*cdf0e10cSrcweir #include "cellrange.hxx"
37*cdf0e10cSrcweir #include "tablemodel.hxx"
38*cdf0e10cSrcweir #include "tablerow.hxx"
39*cdf0e10cSrcweir #include "tablerows.hxx"
40*cdf0e10cSrcweir #include "tablecolumn.hxx"
41*cdf0e10cSrcweir #include "tablecolumns.hxx"
42*cdf0e10cSrcweir #include "tablelayouter.hxx"
43*cdf0e10cSrcweir #include "svx/svdotable.hxx"
44*cdf0e10cSrcweir #include "editeng/borderline.hxx"
45*cdf0e10cSrcweir #include "editeng/boxitem.hxx"
46*cdf0e10cSrcweir #include "svx/svdmodel.hxx"
47*cdf0e10cSrcweir #include "svx/svdstr.hrc"
48*cdf0e10cSrcweir #include "svx/svdglob.hxx"
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir using ::rtl::OUString;
51*cdf0e10cSrcweir using ::com::sun::star::awt::XLayoutConstrains;
52*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
53*cdf0e10cSrcweir using namespace ::com::sun::star::table;
54*cdf0e10cSrcweir using namespace ::com::sun::star::lang;
55*cdf0e10cSrcweir using namespace ::com::sun::star::container;
56*cdf0e10cSrcweir using namespace ::com::sun::star::beans;
57*cdf0e10cSrcweir using namespace ::com::sun::star::table;
58*cdf0e10cSrcweir using namespace ::com::sun::star::text;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir // -----------------------------------------------------------------------------
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir namespace sdr { namespace table {
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir // -----------------------------------------------------------------------------
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir static SvxBorderLine gEmptyBorder;
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir // -----------------------------------------------------------------------------
69*cdf0e10cSrcweir 
70*cdf0e10cSrcweir TableLayouter::TableLayouter( const TableModelRef& xTableModel )
71*cdf0e10cSrcweir : mxTable( xTableModel )
72*cdf0e10cSrcweir , meWritingMode( WritingMode_LR_TB )
73*cdf0e10cSrcweir , msSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) )
74*cdf0e10cSrcweir {
75*cdf0e10cSrcweir }
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir // -----------------------------------------------------------------------------
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir TableLayouter::~TableLayouter()
80*cdf0e10cSrcweir {
81*cdf0e10cSrcweir 	ClearBorderLayout();
82*cdf0e10cSrcweir }
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir // -----------------------------------------------------------------------------
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir basegfx::B2ITuple TableLayouter::getCellSize( const CellPos& rPos  ) const
87*cdf0e10cSrcweir {
88*cdf0e10cSrcweir 	sal_Int32 width = 0;
89*cdf0e10cSrcweir 	sal_Int32 height = 0;
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir 	try
92*cdf0e10cSrcweir 	{
93*cdf0e10cSrcweir 		CellRef xCell( getCell( rPos ) );
94*cdf0e10cSrcweir 		if( xCell.is() && !xCell->isMerged() )
95*cdf0e10cSrcweir 		{
96*cdf0e10cSrcweir 			CellPos aPos( rPos );
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir 			sal_Int32 nRowCount = getRowCount();
99*cdf0e10cSrcweir 			sal_Int32 nRowSpan = std::max( xCell->getRowSpan(), (sal_Int32)1 );
100*cdf0e10cSrcweir 			while( nRowSpan && (aPos.mnRow < nRowCount) )
101*cdf0e10cSrcweir 			{
102*cdf0e10cSrcweir                 if( ((sal_Int32)maRows.size()) <= aPos.mnRow )
103*cdf0e10cSrcweir                     break;
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir 				height += maRows[aPos.mnRow++].mnSize;
106*cdf0e10cSrcweir 				nRowSpan--;
107*cdf0e10cSrcweir 			}
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir 			sal_Int32 nColCount = getColumnCount();
110*cdf0e10cSrcweir 			sal_Int32 nColSpan = std::max( xCell->getColumnSpan(), (sal_Int32)1 );
111*cdf0e10cSrcweir 			while( nColSpan && (aPos.mnCol < nColCount ) )
112*cdf0e10cSrcweir 			{
113*cdf0e10cSrcweir                 if( ((sal_Int32)maColumns.size()) <= aPos.mnCol )
114*cdf0e10cSrcweir                     break;
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir                 width += maColumns[aPos.mnCol++].mnSize;
117*cdf0e10cSrcweir 				nColSpan--;
118*cdf0e10cSrcweir 			}
119*cdf0e10cSrcweir 		}
120*cdf0e10cSrcweir 	}
121*cdf0e10cSrcweir 	catch( Exception& )
122*cdf0e10cSrcweir 	{
123*cdf0e10cSrcweir 		DBG_ERROR( "TableLayouter::getCellSize(), exception caught!" );
124*cdf0e10cSrcweir 	}
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir 	return basegfx::B2ITuple( width, height );
127*cdf0e10cSrcweir }
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir // -----------------------------------------------------------------------------
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir bool TableLayouter::getCellArea( const CellPos& rPos, basegfx::B2IRectangle& rArea ) const
132*cdf0e10cSrcweir {
133*cdf0e10cSrcweir 	try
134*cdf0e10cSrcweir 	{
135*cdf0e10cSrcweir 		CellRef xCell( getCell( rPos ) );
136*cdf0e10cSrcweir 		if( xCell.is() && !xCell->isMerged() && isValid(rPos) )
137*cdf0e10cSrcweir 		{
138*cdf0e10cSrcweir 			const basegfx::B2ITuple aCellSize( getCellSize( rPos ) );
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir             if( (rPos.mnCol < ((sal_Int32)maColumns.size()) && (rPos.mnRow < ((sal_Int32)maRows.size()) ) ) )
141*cdf0e10cSrcweir             {
142*cdf0e10cSrcweir     			const sal_Int32 x = maColumns[rPos.mnCol].mnPos;
143*cdf0e10cSrcweir 	    		const sal_Int32 y = maRows[rPos.mnRow].mnPos;
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir 	    		rArea = basegfx::B2IRectangle( x, y, x + aCellSize.getX(), y + aCellSize.getY()  );
146*cdf0e10cSrcweir 		    	return true;
147*cdf0e10cSrcweir             }
148*cdf0e10cSrcweir 		}
149*cdf0e10cSrcweir 	}
150*cdf0e10cSrcweir 	catch( Exception& )
151*cdf0e10cSrcweir 	{
152*cdf0e10cSrcweir 		DBG_ERROR( "TableLayouter::getCellSize(), exception caught!" );
153*cdf0e10cSrcweir 	}
154*cdf0e10cSrcweir 	return false;
155*cdf0e10cSrcweir }
156*cdf0e10cSrcweir 
157*cdf0e10cSrcweir // -----------------------------------------------------------------------------
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir sal_Int32 TableLayouter::getRowHeight( sal_Int32 nRow )
160*cdf0e10cSrcweir {
161*cdf0e10cSrcweir 	if( isValidRow(nRow) )
162*cdf0e10cSrcweir 		return maRows[nRow].mnSize;
163*cdf0e10cSrcweir 	else
164*cdf0e10cSrcweir 		return 0;
165*cdf0e10cSrcweir }
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir // -----------------------------------------------------------------------------
168*cdf0e10cSrcweir 
169*cdf0e10cSrcweir void TableLayouter::setRowHeight( sal_Int32 nRow, sal_Int32 nHeight )
170*cdf0e10cSrcweir {
171*cdf0e10cSrcweir 	if( isValidRow(nRow) )
172*cdf0e10cSrcweir 	{
173*cdf0e10cSrcweir 		maRows[nRow].mnSize = nHeight;
174*cdf0e10cSrcweir 	}
175*cdf0e10cSrcweir 	else
176*cdf0e10cSrcweir 	{
177*cdf0e10cSrcweir 		DBG_ERROR( "TableLayouter::setRowHeight(), row out of range!" );
178*cdf0e10cSrcweir 	}
179*cdf0e10cSrcweir }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir // -----------------------------------------------------------------------------
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir sal_Int32 TableLayouter::getColumnWidth( sal_Int32 nColumn )
184*cdf0e10cSrcweir {
185*cdf0e10cSrcweir 	if( isValidColumn(nColumn) )
186*cdf0e10cSrcweir 		return maColumns[nColumn].mnSize;
187*cdf0e10cSrcweir 	else
188*cdf0e10cSrcweir 		return 0;
189*cdf0e10cSrcweir }
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir // -----------------------------------------------------------------------------
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir void TableLayouter::setColumnWidth( sal_Int32 nColumn, sal_Int32 nWidth )
194*cdf0e10cSrcweir {
195*cdf0e10cSrcweir 	if( isValidColumn(nColumn) )
196*cdf0e10cSrcweir 		maColumns[nColumn].mnSize = nWidth;
197*cdf0e10cSrcweir 	else
198*cdf0e10cSrcweir 		DBG_ERROR( "TableLayouter::setColumnWidth(), column out of range!" );
199*cdf0e10cSrcweir }
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir // -----------------------------------------------------------------------------
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir bool TableLayouter::isEdgeVisible( sal_Int32 nEdgeX, sal_Int32 nEdgeY, bool bHorizontal ) const
204*cdf0e10cSrcweir {
205*cdf0e10cSrcweir 	const BorderLineMap& rMap = bHorizontal ? maHorizontalBorders : maVerticalBorders;
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir 	if( (nEdgeX >= 0) && (nEdgeX < sal::static_int_cast<sal_Int32>(rMap.size())) &&
208*cdf0e10cSrcweir 		(nEdgeY >= 0) && (nEdgeY < sal::static_int_cast<sal_Int32>(rMap[nEdgeX].size())) )
209*cdf0e10cSrcweir 	{
210*cdf0e10cSrcweir 		return rMap[nEdgeX][nEdgeY] != 0;
211*cdf0e10cSrcweir 	}
212*cdf0e10cSrcweir 	else
213*cdf0e10cSrcweir 	{
214*cdf0e10cSrcweir 		OSL_ENSURE( false, "sdr::table::TableLayouter::getBorderLine(), invalid edge!" );
215*cdf0e10cSrcweir 	}
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir 	return false;
218*cdf0e10cSrcweir }
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir // -----------------------------------------------------------------------------
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir /** returns the requested borderline in rpBorderLine or a null pointer if there is no border at this edge */
223*cdf0e10cSrcweir SvxBorderLine* TableLayouter::getBorderLine( sal_Int32 nEdgeX, sal_Int32 nEdgeY, bool bHorizontal )const
224*cdf0e10cSrcweir {
225*cdf0e10cSrcweir 	SvxBorderLine* pLine = 0;
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir 	const BorderLineMap& rMap = bHorizontal ? maHorizontalBorders : maVerticalBorders;
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir 	if( (nEdgeX >= 0) && (nEdgeX < sal::static_int_cast<sal_Int32>(rMap.size())) &&
230*cdf0e10cSrcweir 		(nEdgeY >= 0) && (nEdgeY < sal::static_int_cast<sal_Int32>(rMap[nEdgeX].size())) )
231*cdf0e10cSrcweir 	{
232*cdf0e10cSrcweir 		pLine = rMap[nEdgeX][nEdgeY];
233*cdf0e10cSrcweir 		if( pLine == &gEmptyBorder )
234*cdf0e10cSrcweir 			pLine = 0;
235*cdf0e10cSrcweir 	}
236*cdf0e10cSrcweir 	else
237*cdf0e10cSrcweir 	{
238*cdf0e10cSrcweir 		OSL_ENSURE( false, "sdr::table::TableLayouter::getBorderLine(), invalid edge!" );
239*cdf0e10cSrcweir 	}
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir 	return pLine;
242*cdf0e10cSrcweir }
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir // -----------------------------------------------------------------------------
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir sal_Int32 TableLayouter::getHorizontalEdge( int nEdgeY, sal_Int32* pnMin /*= 0*/, sal_Int32* pnMax /*= 0*/ )
247*cdf0e10cSrcweir {
248*cdf0e10cSrcweir 	sal_Int32 nRet = 0;
249*cdf0e10cSrcweir 	if( (nEdgeY >= 0) && (nEdgeY <= getRowCount() ) )
250*cdf0e10cSrcweir 		nRet = maRows[std::min((sal_Int32)nEdgeY,getRowCount()-1)].mnPos;
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir 	if( nEdgeY == getRowCount() )
253*cdf0e10cSrcweir 		nRet += maRows[nEdgeY - 1].mnSize;
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir 	if( pnMin )
256*cdf0e10cSrcweir 	{
257*cdf0e10cSrcweir 		if( (nEdgeY > 0) && (nEdgeY <= getRowCount() ) )
258*cdf0e10cSrcweir 		{
259*cdf0e10cSrcweir 			*pnMin = maRows[nEdgeY-1].mnPos + 600; // todo
260*cdf0e10cSrcweir 		}
261*cdf0e10cSrcweir 		else
262*cdf0e10cSrcweir 		{
263*cdf0e10cSrcweir 			*pnMin = nRet;
264*cdf0e10cSrcweir 		}
265*cdf0e10cSrcweir 	}
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir 	if( pnMax )
268*cdf0e10cSrcweir 	{
269*cdf0e10cSrcweir 		*pnMax = 0x0fffffff;
270*cdf0e10cSrcweir 	}
271*cdf0e10cSrcweir 	return nRet;
272*cdf0e10cSrcweir }
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir // -----------------------------------------------------------------------------
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir sal_Int32 TableLayouter::getVerticalEdge( int nEdgeX, sal_Int32* pnMin /*= 0*/, sal_Int32* pnMax /*= 0*/ )
277*cdf0e10cSrcweir {
278*cdf0e10cSrcweir 	sal_Int32 nRet = 0;
279*cdf0e10cSrcweir 
280*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
281*cdf0e10cSrcweir 	if( (nEdgeX >= 0) && (nEdgeX <= nColCount ) )
282*cdf0e10cSrcweir 		nRet = maColumns[std::min((sal_Int32)nEdgeX,nColCount-1)].mnPos;
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir 	const bool bRTL = meWritingMode == WritingMode_RL_TB;
285*cdf0e10cSrcweir 	if( bRTL )
286*cdf0e10cSrcweir 	{
287*cdf0e10cSrcweir 		if( (nEdgeX >= 0) && (nEdgeX < nColCount) )
288*cdf0e10cSrcweir 			nRet += maColumns[nEdgeX].mnSize;
289*cdf0e10cSrcweir 	}
290*cdf0e10cSrcweir 	else
291*cdf0e10cSrcweir 	{
292*cdf0e10cSrcweir 		if( nEdgeX == getColumnCount() )
293*cdf0e10cSrcweir 			nRet += maColumns[nEdgeX - 1].mnSize;
294*cdf0e10cSrcweir 	}
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 	if( pnMin )
297*cdf0e10cSrcweir 	{
298*cdf0e10cSrcweir 		*pnMin = nRet;
299*cdf0e10cSrcweir 		if( bRTL )
300*cdf0e10cSrcweir 		{
301*cdf0e10cSrcweir 			if( nEdgeX < nColCount )
302*cdf0e10cSrcweir 				*pnMin = nRet - maColumns[nEdgeX].mnSize + getMinimumColumnWidth(nEdgeX);
303*cdf0e10cSrcweir 		}
304*cdf0e10cSrcweir 		else
305*cdf0e10cSrcweir 		{
306*cdf0e10cSrcweir 			if( (nEdgeX > 0) && (nEdgeX <= nColCount ) )
307*cdf0e10cSrcweir 				*pnMin = maColumns[nEdgeX-1].mnPos + getMinimumColumnWidth( nEdgeX-1 );
308*cdf0e10cSrcweir 		}
309*cdf0e10cSrcweir 	}
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir 	if( pnMax )
312*cdf0e10cSrcweir 	{
313*cdf0e10cSrcweir 		*pnMax = 0x0fffffff; // todo
314*cdf0e10cSrcweir 		if( bRTL )
315*cdf0e10cSrcweir 		{
316*cdf0e10cSrcweir 			if( nEdgeX > 0 )
317*cdf0e10cSrcweir 				*pnMax = nRet + maColumns[nEdgeX-1].mnSize - getMinimumColumnWidth( nEdgeX-1 );
318*cdf0e10cSrcweir 		}
319*cdf0e10cSrcweir 		else
320*cdf0e10cSrcweir 		{
321*cdf0e10cSrcweir 			if( (nEdgeX >= 0) && (nEdgeX < nColCount ) )
322*cdf0e10cSrcweir 				*pnMax = maColumns[nEdgeX].mnPos + maColumns[nEdgeX].mnSize - getMinimumColumnWidth( nEdgeX );
323*cdf0e10cSrcweir 		}
324*cdf0e10cSrcweir 	}
325*cdf0e10cSrcweir 
326*cdf0e10cSrcweir 	return nRet;
327*cdf0e10cSrcweir }
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir // -----------------------------------------------------------------------------
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir static bool checkMergeOrigin( const TableModelRef& xTable, sal_Int32 nMergedX, sal_Int32 nMergedY, sal_Int32 nCellX, sal_Int32 nCellY, bool& bRunning )
332*cdf0e10cSrcweir {
333*cdf0e10cSrcweir     Reference< XMergeableCell > xCell( xTable->getCellByPosition( nCellX, nCellY ), UNO_QUERY );
334*cdf0e10cSrcweir     if( xCell.is() && !xCell->isMerged() )
335*cdf0e10cSrcweir     {
336*cdf0e10cSrcweir         const sal_Int32 nRight = xCell->getColumnSpan() + nCellX;
337*cdf0e10cSrcweir         const sal_Int32 nBottom = xCell->getRowSpan() + nCellY;
338*cdf0e10cSrcweir         if( (nMergedX < nRight) && (nMergedY < nBottom) )
339*cdf0e10cSrcweir             return true;
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir         bRunning = false;
342*cdf0e10cSrcweir     }
343*cdf0e10cSrcweir     return false;
344*cdf0e10cSrcweir }
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir /** returns true if the cell(nMergedX,nMergedY) is merged with other cells.
347*cdf0e10cSrcweir 	the returned cell( rOriginX, rOriginY ) is the origin( top left cell ) of the merge.
348*cdf0e10cSrcweir */
349*cdf0e10cSrcweir bool findMergeOrigin( const TableModelRef& xTable, sal_Int32 nMergedX, sal_Int32 nMergedY, sal_Int32& rOriginX, sal_Int32& rOriginY )
350*cdf0e10cSrcweir {
351*cdf0e10cSrcweir 	rOriginX = nMergedX;
352*cdf0e10cSrcweir 	rOriginY = nMergedY;
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir 	if( xTable.is() ) try
355*cdf0e10cSrcweir 	{
356*cdf0e10cSrcweir 		// check if this cell already the origin or not merged at all
357*cdf0e10cSrcweir 		Reference< XMergeableCell > xCell( xTable->getCellByPosition( nMergedX, nMergedY ), UNO_QUERY_THROW );
358*cdf0e10cSrcweir 		if( !xCell.is() || !xCell->isMerged() )
359*cdf0e10cSrcweir 			return true;
360*cdf0e10cSrcweir 
361*cdf0e10cSrcweir         bool bCheckVert = true;
362*cdf0e10cSrcweir         bool bCheckHorz = true;
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir         sal_Int32 nMinCol = 0;
365*cdf0e10cSrcweir         sal_Int32 nMinRow = 0;
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir         sal_Int32 nStep = 1, i;
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir         sal_Int32 nRow, nCol;
370*cdf0e10cSrcweir         do
371*cdf0e10cSrcweir         {
372*cdf0e10cSrcweir             if( bCheckVert )
373*cdf0e10cSrcweir             {
374*cdf0e10cSrcweir                 nRow = nMergedY - nStep;
375*cdf0e10cSrcweir                 if( nRow >= nMinRow )
376*cdf0e10cSrcweir                 {
377*cdf0e10cSrcweir                     nCol = nMergedX;
378*cdf0e10cSrcweir                     for( i = 0; (i <= nStep) && (nCol >= nMinCol); i++, nCol-- )
379*cdf0e10cSrcweir                     {
380*cdf0e10cSrcweir                         if( checkMergeOrigin( xTable, nMergedX, nMergedY, nCol, nRow, bCheckVert ) )
381*cdf0e10cSrcweir                         {
382*cdf0e10cSrcweir                             rOriginX = nCol; rOriginY = nRow;
383*cdf0e10cSrcweir                             return true;
384*cdf0e10cSrcweir                         }
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir                         if( !bCheckVert )
387*cdf0e10cSrcweir                         {
388*cdf0e10cSrcweir                             if( nCol == nMergedX )
389*cdf0e10cSrcweir                             {
390*cdf0e10cSrcweir                                 nMinRow = nRow+1;
391*cdf0e10cSrcweir                             }
392*cdf0e10cSrcweir                             else
393*cdf0e10cSrcweir                             {
394*cdf0e10cSrcweir                                 bCheckVert = true;
395*cdf0e10cSrcweir                             }
396*cdf0e10cSrcweir                             break;
397*cdf0e10cSrcweir                         }
398*cdf0e10cSrcweir                     }
399*cdf0e10cSrcweir                 }
400*cdf0e10cSrcweir                 else
401*cdf0e10cSrcweir                 {
402*cdf0e10cSrcweir                     bCheckVert = false;
403*cdf0e10cSrcweir                 }
404*cdf0e10cSrcweir             }
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir             if( bCheckHorz )
407*cdf0e10cSrcweir             {
408*cdf0e10cSrcweir                 nCol = nMergedX - nStep;
409*cdf0e10cSrcweir                 if( nCol >= nMinCol )
410*cdf0e10cSrcweir                 {
411*cdf0e10cSrcweir                     nRow = nMergedY;
412*cdf0e10cSrcweir                     for( i = 0; (i < nStep) && (nRow >= nMinRow); i++, nRow-- )
413*cdf0e10cSrcweir                     {
414*cdf0e10cSrcweir                         if( checkMergeOrigin( xTable, nMergedX, nMergedY, nCol, nRow, bCheckHorz ) )
415*cdf0e10cSrcweir                         {
416*cdf0e10cSrcweir                             rOriginX = nCol; rOriginY = nRow;
417*cdf0e10cSrcweir                             return true;
418*cdf0e10cSrcweir                         }
419*cdf0e10cSrcweir 
420*cdf0e10cSrcweir                         if( !bCheckHorz )
421*cdf0e10cSrcweir                         {
422*cdf0e10cSrcweir                             if( nRow == nMergedY )
423*cdf0e10cSrcweir                             {
424*cdf0e10cSrcweir                                 nMinCol = nCol+1;
425*cdf0e10cSrcweir                             }
426*cdf0e10cSrcweir                             else
427*cdf0e10cSrcweir                             {
428*cdf0e10cSrcweir                                 bCheckHorz = true;
429*cdf0e10cSrcweir                             }
430*cdf0e10cSrcweir                             break;
431*cdf0e10cSrcweir                         }
432*cdf0e10cSrcweir                     }
433*cdf0e10cSrcweir                 }
434*cdf0e10cSrcweir                 else
435*cdf0e10cSrcweir                 {
436*cdf0e10cSrcweir                     bCheckHorz = false;
437*cdf0e10cSrcweir                 }
438*cdf0e10cSrcweir             }
439*cdf0e10cSrcweir             nStep++;
440*cdf0e10cSrcweir         }
441*cdf0e10cSrcweir         while( bCheckVert || bCheckHorz );
442*cdf0e10cSrcweir 	}
443*cdf0e10cSrcweir 	catch( Exception& )
444*cdf0e10cSrcweir 	{
445*cdf0e10cSrcweir 		DBG_ERROR("sdr::table::TableLayouter::findMergeOrigin(), exception caught!");
446*cdf0e10cSrcweir 	}
447*cdf0e10cSrcweir 	return false;
448*cdf0e10cSrcweir }
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir // -----------------------------------------------------------------------------
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir sal_Int32 TableLayouter::getMinimumColumnWidth( sal_Int32 nColumn )
453*cdf0e10cSrcweir {
454*cdf0e10cSrcweir 	if( isValidColumn( nColumn ) )
455*cdf0e10cSrcweir 	{
456*cdf0e10cSrcweir 		return maColumns[nColumn].mnMinSize;
457*cdf0e10cSrcweir 	}
458*cdf0e10cSrcweir 	else
459*cdf0e10cSrcweir 	{
460*cdf0e10cSrcweir 		DBG_ERROR( "TableLayouter::getMinimumColumnWidth(), column out of range!" );
461*cdf0e10cSrcweir 		return 0;
462*cdf0e10cSrcweir 	}
463*cdf0e10cSrcweir }
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir // -----------------------------------------------------------------------------
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir sal_Int32 TableLayouter::distribute( LayoutVector& rLayouts, sal_Int32 nDistribute )
468*cdf0e10cSrcweir {
469*cdf0e10cSrcweir 	// break loops after 100 runs to avoid freezing office due to developer error
470*cdf0e10cSrcweir 	sal_Int32 nSafe = 100;
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir 	const sal_Size nCount = rLayouts.size();
473*cdf0e10cSrcweir 	sal_Size nIndex;
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir 	bool bConstrainsBroken = false;
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir 	do
478*cdf0e10cSrcweir 	{
479*cdf0e10cSrcweir 		// first enforce minimum size constrains on all entities
480*cdf0e10cSrcweir 		for( nIndex = 0; nIndex < nCount; ++nIndex )
481*cdf0e10cSrcweir 		{
482*cdf0e10cSrcweir 			Layout& rLayout = rLayouts[nIndex];
483*cdf0e10cSrcweir 			if( rLayout.mnSize < rLayout.mnMinSize )
484*cdf0e10cSrcweir 			{
485*cdf0e10cSrcweir 				nDistribute -= rLayout.mnMinSize - rLayout.mnSize;
486*cdf0e10cSrcweir 				rLayout.mnSize = rLayout.mnMinSize;
487*cdf0e10cSrcweir 			}
488*cdf0e10cSrcweir 		}
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir 		// calculate current width
491*cdf0e10cSrcweir 		// if nDistribute is < 0 (shrinking), entities that are already
492*cdf0e10cSrcweir 		// at minimum width are not counted
493*cdf0e10cSrcweir 		sal_Int32 nCurrentWidth = 0;
494*cdf0e10cSrcweir 		for( nIndex = 0; nIndex < nCount; ++nIndex )
495*cdf0e10cSrcweir 		{
496*cdf0e10cSrcweir 			Layout& rLayout = rLayouts[nIndex];
497*cdf0e10cSrcweir 			if( (nDistribute > 0) || (rLayout.mnSize > rLayout.mnMinSize) )
498*cdf0e10cSrcweir 				nCurrentWidth += rLayout.mnSize;
499*cdf0e10cSrcweir 		}
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir 		bConstrainsBroken = false;
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 		// now distribute over entities
504*cdf0e10cSrcweir 		if( (nCurrentWidth != 0) && (nDistribute != 0) )
505*cdf0e10cSrcweir 		{
506*cdf0e10cSrcweir 			sal_Int32 nDistributed = nDistribute;
507*cdf0e10cSrcweir 			for( nIndex = 0; nIndex < nCount; ++nIndex )
508*cdf0e10cSrcweir 			{
509*cdf0e10cSrcweir 				Layout& rLayout = rLayouts[nIndex];
510*cdf0e10cSrcweir 				if( (nDistribute > 0) || (rLayout.mnSize > rLayout.mnMinSize) )
511*cdf0e10cSrcweir 				{
512*cdf0e10cSrcweir 					sal_Int32 n;
513*cdf0e10cSrcweir 					if( nIndex == (nCount-1) )
514*cdf0e10cSrcweir 						n = nDistributed; // for last entitie, use up rest
515*cdf0e10cSrcweir 					else
516*cdf0e10cSrcweir 						n  = (nDistribute * rLayout.mnSize) / nCurrentWidth; //
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir 					nDistributed -= n;
519*cdf0e10cSrcweir 					rLayout.mnSize += n;
520*cdf0e10cSrcweir 
521*cdf0e10cSrcweir 					if( rLayout.mnSize < rLayout.mnMinSize )
522*cdf0e10cSrcweir 						bConstrainsBroken = true;
523*cdf0e10cSrcweir 				}
524*cdf0e10cSrcweir 			}
525*cdf0e10cSrcweir 		}
526*cdf0e10cSrcweir 	} while( bConstrainsBroken && --nSafe );
527*cdf0e10cSrcweir 
528*cdf0e10cSrcweir 	sal_Int32 nSize = 0;
529*cdf0e10cSrcweir 	for( nIndex = 0; nIndex < nCount; ++nIndex )
530*cdf0e10cSrcweir 		nSize += rLayouts[nIndex].mnSize;
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir 	return nSize;
533*cdf0e10cSrcweir }
534*cdf0e10cSrcweir 
535*cdf0e10cSrcweir // -----------------------------------------------------------------------------
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir typedef std::vector< CellRef > MergeableCellVector;
538*cdf0e10cSrcweir typedef std::vector< MergeableCellVector > MergeVector;
539*cdf0e10cSrcweir typedef std::vector< sal_Int32 > Int32Vector;
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir // -----------------------------------------------------------------------------
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir void TableLayouter::LayoutTableWidth( Rectangle& rArea, bool bFit )
544*cdf0e10cSrcweir {
545*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
546*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
547*cdf0e10cSrcweir 	if( nColCount == 0 )
548*cdf0e10cSrcweir 		return;
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir 	MergeVector aMergedCells( nColCount );
551*cdf0e10cSrcweir 	Int32Vector aOptimalColumns;
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir 	const OUString sOptimalSize( RTL_CONSTASCII_USTRINGPARAM("OptimalSize") );
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir 	if( sal::static_int_cast< sal_Int32 >( maColumns.size() ) != nColCount )
556*cdf0e10cSrcweir 		maColumns.resize( nColCount );
557*cdf0e10cSrcweir 
558*cdf0e10cSrcweir 	Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
559*cdf0e10cSrcweir 
560*cdf0e10cSrcweir 	// first calculate current width and initial minimum width per column,
561*cdf0e10cSrcweir 	// merged cells will be counted later
562*cdf0e10cSrcweir 	sal_Int32 nCurrentWidth = 0;
563*cdf0e10cSrcweir 	sal_Int32 nCol = 0, nRow = 0;
564*cdf0e10cSrcweir 	for( nCol = 0; nCol < nColCount; nCol++ )
565*cdf0e10cSrcweir 	{
566*cdf0e10cSrcweir 		sal_Int32 nMinWidth = 0;
567*cdf0e10cSrcweir 
568*cdf0e10cSrcweir 		bool bIsEmpty = true; // check if all cells in this column are merged
569*cdf0e10cSrcweir 
570*cdf0e10cSrcweir 		for( nRow = 0; nRow < nRowCount; ++nRow )
571*cdf0e10cSrcweir 		{
572*cdf0e10cSrcweir 			CellRef xCell( getCell( CellPos( nCol, nRow ) ) );
573*cdf0e10cSrcweir 			if( xCell.is() && !xCell->isMerged() )
574*cdf0e10cSrcweir 			{
575*cdf0e10cSrcweir 				bIsEmpty = false;
576*cdf0e10cSrcweir 
577*cdf0e10cSrcweir 				sal_Int32 nColSpan = xCell->getColumnSpan();
578*cdf0e10cSrcweir 				if( nColSpan > 1 )
579*cdf0e10cSrcweir 				{
580*cdf0e10cSrcweir 					// merged cells will be evaluated later
581*cdf0e10cSrcweir 					aMergedCells[nCol+nColSpan-1].push_back( xCell );
582*cdf0e10cSrcweir 				}
583*cdf0e10cSrcweir 				else
584*cdf0e10cSrcweir 				{
585*cdf0e10cSrcweir 					nMinWidth = std::max( nMinWidth, xCell->getMinimumSize().Width );
586*cdf0e10cSrcweir 				}
587*cdf0e10cSrcweir 			}
588*cdf0e10cSrcweir 		}
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir 		maColumns[nCol].mnMinSize = nMinWidth;
591*cdf0e10cSrcweir 
592*cdf0e10cSrcweir 		if( bIsEmpty )
593*cdf0e10cSrcweir 		{
594*cdf0e10cSrcweir 			maColumns[nCol].mnSize = 0;
595*cdf0e10cSrcweir 		}
596*cdf0e10cSrcweir 		else
597*cdf0e10cSrcweir 		{
598*cdf0e10cSrcweir 			sal_Int32 nColWidth = 0;
599*cdf0e10cSrcweir 			Reference< XPropertySet > xColSet( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
600*cdf0e10cSrcweir 			sal_Bool bOptimal = sal_False;
601*cdf0e10cSrcweir 			xColSet->getPropertyValue( sOptimalSize ) >>= bOptimal;
602*cdf0e10cSrcweir 			if( bOptimal )
603*cdf0e10cSrcweir 			{
604*cdf0e10cSrcweir 				aOptimalColumns.push_back(nCol);
605*cdf0e10cSrcweir 			}
606*cdf0e10cSrcweir 			else
607*cdf0e10cSrcweir 			{
608*cdf0e10cSrcweir 				xColSet->getPropertyValue( msSize ) >>= nColWidth;
609*cdf0e10cSrcweir 			}
610*cdf0e10cSrcweir 
611*cdf0e10cSrcweir 			maColumns[nCol].mnSize = nColWidth;
612*cdf0e10cSrcweir 
613*cdf0e10cSrcweir 			if( maColumns[nCol].mnSize < nMinWidth )
614*cdf0e10cSrcweir 				maColumns[nCol].mnSize = nMinWidth;
615*cdf0e10cSrcweir 
616*cdf0e10cSrcweir 			nCurrentWidth += maColumns[nCol].mnSize;
617*cdf0e10cSrcweir 		}
618*cdf0e10cSrcweir 	}
619*cdf0e10cSrcweir 
620*cdf0e10cSrcweir 	// if we have optimal sized rows, distribute what is given (left)
621*cdf0e10cSrcweir 	if( !bFit && !aOptimalColumns.empty() && (nCurrentWidth < rArea.getWidth()) )
622*cdf0e10cSrcweir 	{
623*cdf0e10cSrcweir 		sal_Int32 nLeft = rArea.getWidth() - nCurrentWidth;
624*cdf0e10cSrcweir 		sal_Int32 nDistribute = nLeft / aOptimalColumns.size();
625*cdf0e10cSrcweir 
626*cdf0e10cSrcweir 		Int32Vector::iterator iter( aOptimalColumns.begin() );
627*cdf0e10cSrcweir 		while( iter != aOptimalColumns.end() )
628*cdf0e10cSrcweir 		{
629*cdf0e10cSrcweir 			sal_Int32 nOptCol = (*iter++);
630*cdf0e10cSrcweir 			if( iter == aOptimalColumns.end() )
631*cdf0e10cSrcweir 				nDistribute = nLeft;
632*cdf0e10cSrcweir 
633*cdf0e10cSrcweir 			maColumns[nOptCol].mnSize += nDistribute;
634*cdf0e10cSrcweir 			nLeft -= nDistribute;
635*cdf0e10cSrcweir 		}
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir 		DBG_ASSERT( nLeft == 0, "svx::TableLayouter::LayoutTableWidtht(), layouting failed!" );
638*cdf0e10cSrcweir 	}
639*cdf0e10cSrcweir 
640*cdf0e10cSrcweir 	// now check if merged cells fit
641*cdf0e10cSrcweir 	for( nCol = 1; nCol < nColCount; ++nCol )
642*cdf0e10cSrcweir 	{
643*cdf0e10cSrcweir 		bool bChanges = false;
644*cdf0e10cSrcweir 		MergeableCellVector::iterator iter( aMergedCells[nCol].begin() );
645*cdf0e10cSrcweir 
646*cdf0e10cSrcweir 		const sal_Int32 nOldSize = maColumns[nCol].mnSize;
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir 		while( iter != aMergedCells[nCol].end() )
649*cdf0e10cSrcweir 		{
650*cdf0e10cSrcweir 			CellRef xCell( (*iter++) );
651*cdf0e10cSrcweir 			sal_Int32 nMinWidth = xCell->getMinimumSize().Width;
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir 			for( sal_Int32 nMCol = nCol - xCell->getColumnSpan() + 1; (nMCol > 0) && (nMCol < nCol); ++nMCol )
654*cdf0e10cSrcweir 				nMinWidth -= maColumns[nMCol].mnSize;
655*cdf0e10cSrcweir 
656*cdf0e10cSrcweir 			if( nMinWidth > maColumns[nCol].mnMinSize )
657*cdf0e10cSrcweir 				maColumns[nCol].mnMinSize = nMinWidth;
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir 			if( nMinWidth > maColumns[nCol].mnSize )
660*cdf0e10cSrcweir 			{
661*cdf0e10cSrcweir 				maColumns[nCol].mnSize = nMinWidth;
662*cdf0e10cSrcweir 				bChanges = true;
663*cdf0e10cSrcweir 			}
664*cdf0e10cSrcweir 		}
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir 		if( bChanges )
667*cdf0e10cSrcweir 			nCurrentWidth += maColumns[nCol].mnSize - nOldSize;
668*cdf0e10cSrcweir 	}
669*cdf0e10cSrcweir 
670*cdf0e10cSrcweir 	// now scale if wanted and needed
671*cdf0e10cSrcweir 	if( bFit && (nCurrentWidth != rArea.getWidth()) )
672*cdf0e10cSrcweir 		distribute( maColumns, rArea.getWidth() - nCurrentWidth );
673*cdf0e10cSrcweir 
674*cdf0e10cSrcweir 	// last step, update left edges
675*cdf0e10cSrcweir 	sal_Int32 nNewWidth = 0;
676*cdf0e10cSrcweir 
677*cdf0e10cSrcweir 	const bool bRTL = meWritingMode == WritingMode_RL_TB;
678*cdf0e10cSrcweir 	RangeIterator<sal_Int32> coliter( 0, nColCount, !bRTL );
679*cdf0e10cSrcweir 	while( coliter.next(nCol ) )
680*cdf0e10cSrcweir 	{
681*cdf0e10cSrcweir 		maColumns[nCol].mnPos = nNewWidth;
682*cdf0e10cSrcweir 		nNewWidth += maColumns[nCol].mnSize;
683*cdf0e10cSrcweir 		if( bFit )
684*cdf0e10cSrcweir 		{
685*cdf0e10cSrcweir 			Reference< XPropertySet > xColSet( xCols->getByIndex(nCol), UNO_QUERY_THROW );
686*cdf0e10cSrcweir 			xColSet->setPropertyValue( msSize, Any( maColumns[nCol].mnSize ) );
687*cdf0e10cSrcweir 		}
688*cdf0e10cSrcweir 	}
689*cdf0e10cSrcweir 
690*cdf0e10cSrcweir 	rArea.SetSize( Size( nNewWidth, rArea.GetHeight() ) );
691*cdf0e10cSrcweir 	updateCells( rArea );
692*cdf0e10cSrcweir }
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir // -----------------------------------------------------------------------------
695*cdf0e10cSrcweir 
696*cdf0e10cSrcweir void TableLayouter::LayoutTableHeight( Rectangle& rArea, bool bFit )
697*cdf0e10cSrcweir {
698*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
699*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
700*cdf0e10cSrcweir 	if( nRowCount == 0 )
701*cdf0e10cSrcweir 		return;
702*cdf0e10cSrcweir 
703*cdf0e10cSrcweir 	Reference< XTableRows > xRows( mxTable->getRows() );
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir 	MergeVector aMergedCells( nRowCount );
706*cdf0e10cSrcweir 	Int32Vector aOptimalRows;
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir 	const OUString sOptimalSize( RTL_CONSTASCII_USTRINGPARAM("OptimalSize") );
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir 	// first calculate current height and initial minimum size per column,
711*cdf0e10cSrcweir 	// merged cells will be counted later
712*cdf0e10cSrcweir 	sal_Int32 nCurrentHeight = 0;
713*cdf0e10cSrcweir 	sal_Int32 nCol, nRow;
714*cdf0e10cSrcweir 	for( nRow = 0; nRow < nRowCount; ++nRow )
715*cdf0e10cSrcweir 	{
716*cdf0e10cSrcweir 		sal_Int32 nMinHeight = 0;
717*cdf0e10cSrcweir 
718*cdf0e10cSrcweir 		bool bIsEmpty = true; // check if all cells in this row are merged
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir 		for( nCol = 0; nCol < nColCount; ++nCol )
721*cdf0e10cSrcweir 		{
722*cdf0e10cSrcweir 			CellRef xCell( getCell( CellPos( nCol, nRow ) ) );
723*cdf0e10cSrcweir 			if( xCell.is() && !xCell->isMerged() )
724*cdf0e10cSrcweir 			{
725*cdf0e10cSrcweir 				bIsEmpty = false;
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir 				sal_Int32 nRowSpan = xCell->getRowSpan();
728*cdf0e10cSrcweir 				if( nRowSpan > 1 )
729*cdf0e10cSrcweir 				{
730*cdf0e10cSrcweir 					// merged cells will be evaluated later
731*cdf0e10cSrcweir 					aMergedCells[nRow+nRowSpan-1].push_back( xCell );
732*cdf0e10cSrcweir 				}
733*cdf0e10cSrcweir 				else
734*cdf0e10cSrcweir 				{
735*cdf0e10cSrcweir 					nMinHeight = std::max( nMinHeight, xCell->getMinimumSize().Height );
736*cdf0e10cSrcweir 				}
737*cdf0e10cSrcweir 			}
738*cdf0e10cSrcweir 		}
739*cdf0e10cSrcweir 
740*cdf0e10cSrcweir 		maRows[nRow].mnMinSize = nMinHeight;
741*cdf0e10cSrcweir 
742*cdf0e10cSrcweir 		if( bIsEmpty )
743*cdf0e10cSrcweir 		{
744*cdf0e10cSrcweir 			maRows[nRow].mnSize = 0;
745*cdf0e10cSrcweir 		}
746*cdf0e10cSrcweir 		else
747*cdf0e10cSrcweir 		{
748*cdf0e10cSrcweir 			sal_Int32 nRowHeight = 0;
749*cdf0e10cSrcweir 			Reference< XPropertySet > xRowSet( xRows->getByIndex(nRow), UNO_QUERY_THROW );
750*cdf0e10cSrcweir 
751*cdf0e10cSrcweir 			sal_Bool bOptimal = sal_False;
752*cdf0e10cSrcweir 			xRowSet->getPropertyValue( sOptimalSize ) >>= bOptimal;
753*cdf0e10cSrcweir 			if( bOptimal )
754*cdf0e10cSrcweir 			{
755*cdf0e10cSrcweir 				aOptimalRows.push_back( nRow );
756*cdf0e10cSrcweir 			}
757*cdf0e10cSrcweir 			else
758*cdf0e10cSrcweir 			{
759*cdf0e10cSrcweir 				xRowSet->getPropertyValue( msSize ) >>= nRowHeight;
760*cdf0e10cSrcweir 			}
761*cdf0e10cSrcweir 
762*cdf0e10cSrcweir 			maRows[nRow].mnSize = nRowHeight;
763*cdf0e10cSrcweir 
764*cdf0e10cSrcweir 			if( maRows[nRow].mnSize < nMinHeight )
765*cdf0e10cSrcweir 				maRows[nRow].mnSize = nMinHeight;
766*cdf0e10cSrcweir 
767*cdf0e10cSrcweir 			nCurrentHeight += maRows[nRow].mnSize;
768*cdf0e10cSrcweir 		}
769*cdf0e10cSrcweir 	}
770*cdf0e10cSrcweir 
771*cdf0e10cSrcweir 	// if we have optimal sized rows, distribute what is given (left)
772*cdf0e10cSrcweir 	if( !bFit && !aOptimalRows.empty() && (nCurrentHeight < rArea.getHeight()) )
773*cdf0e10cSrcweir 	{
774*cdf0e10cSrcweir 		sal_Int32 nLeft = rArea.getHeight() - nCurrentHeight;
775*cdf0e10cSrcweir 		sal_Int32 nDistribute = nLeft / aOptimalRows.size();
776*cdf0e10cSrcweir 
777*cdf0e10cSrcweir 		Int32Vector::iterator iter( aOptimalRows.begin() );
778*cdf0e10cSrcweir 		while( iter != aOptimalRows.end() )
779*cdf0e10cSrcweir 		{
780*cdf0e10cSrcweir 			sal_Int32 nOptRow = (*iter++);
781*cdf0e10cSrcweir 			if( iter == aOptimalRows.end() )
782*cdf0e10cSrcweir 				nDistribute = nLeft;
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir 			maRows[nOptRow].mnSize += nDistribute;
785*cdf0e10cSrcweir 			nLeft -= nDistribute;
786*cdf0e10cSrcweir 
787*cdf0e10cSrcweir 		}
788*cdf0e10cSrcweir 
789*cdf0e10cSrcweir 		DBG_ASSERT( nLeft == 0, "svx::TableLayouter::LayoutTableHeight(), layouting failed!" );
790*cdf0e10cSrcweir 	}
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir 	// now check if merged cells fit
793*cdf0e10cSrcweir 	for( nRow = 1; nRow < nRowCount; ++nRow )
794*cdf0e10cSrcweir 	{
795*cdf0e10cSrcweir 		bool bChanges = false;
796*cdf0e10cSrcweir 		sal_Int32 nOldSize = maRows[nRow].mnSize;
797*cdf0e10cSrcweir 
798*cdf0e10cSrcweir 		MergeableCellVector::iterator iter( aMergedCells[nRow].begin() );
799*cdf0e10cSrcweir 		while( iter != aMergedCells[nRow].end() )
800*cdf0e10cSrcweir 		{
801*cdf0e10cSrcweir 			CellRef xCell( (*iter++) );
802*cdf0e10cSrcweir 			sal_Int32 nMinHeight = xCell->getMinimumSize().Height;
803*cdf0e10cSrcweir 
804*cdf0e10cSrcweir 			for( sal_Int32 nMRow = nRow - xCell->getRowSpan() + 1; (nMRow > 0) && (nMRow < nRow); ++nMRow )
805*cdf0e10cSrcweir 				nMinHeight -= maRows[nMRow].mnSize;
806*cdf0e10cSrcweir 
807*cdf0e10cSrcweir 			if( nMinHeight > maRows[nRow].mnMinSize )
808*cdf0e10cSrcweir 				maRows[nRow].mnMinSize = nMinHeight;
809*cdf0e10cSrcweir 
810*cdf0e10cSrcweir 			if( nMinHeight > maRows[nRow].mnSize )
811*cdf0e10cSrcweir 			{
812*cdf0e10cSrcweir 				maRows[nRow].mnSize = nMinHeight;
813*cdf0e10cSrcweir 				bChanges = true;
814*cdf0e10cSrcweir 			}
815*cdf0e10cSrcweir 		}
816*cdf0e10cSrcweir 		if( bChanges )
817*cdf0e10cSrcweir 			nCurrentHeight += maRows[nRow].mnSize - nOldSize;
818*cdf0e10cSrcweir 	}
819*cdf0e10cSrcweir 
820*cdf0e10cSrcweir 	// now scale if wanted and needed
821*cdf0e10cSrcweir 	if( bFit && nCurrentHeight != rArea.getHeight() )
822*cdf0e10cSrcweir 		distribute( maRows, rArea.getHeight() - nCurrentHeight );
823*cdf0e10cSrcweir 
824*cdf0e10cSrcweir 	// last step, update left edges
825*cdf0e10cSrcweir 	sal_Int32 nNewHeight = 0;
826*cdf0e10cSrcweir 	for( nRow = 0; nRow < nRowCount; ++nRow )
827*cdf0e10cSrcweir 	{
828*cdf0e10cSrcweir 		maRows[nRow].mnPos = nNewHeight;
829*cdf0e10cSrcweir 		nNewHeight += maRows[nRow].mnSize;
830*cdf0e10cSrcweir 
831*cdf0e10cSrcweir 		if( bFit )
832*cdf0e10cSrcweir 		{
833*cdf0e10cSrcweir 			Reference< XPropertySet > xRowSet( xRows->getByIndex(nRow), UNO_QUERY_THROW );
834*cdf0e10cSrcweir 			xRowSet->setPropertyValue( msSize, Any( maRows[nRow].mnSize ) );
835*cdf0e10cSrcweir 		}
836*cdf0e10cSrcweir 	}
837*cdf0e10cSrcweir 
838*cdf0e10cSrcweir 	rArea.SetSize( Size( rArea.GetWidth(), nNewHeight ) );
839*cdf0e10cSrcweir 	updateCells( rArea );
840*cdf0e10cSrcweir }
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir // -----------------------------------------------------------------------------
843*cdf0e10cSrcweir 
844*cdf0e10cSrcweir /** try to fit the table into the given rectangle.
845*cdf0e10cSrcweir 	If the rectangle is to small, it will be grown to fit the table. */
846*cdf0e10cSrcweir void TableLayouter::LayoutTable( Rectangle& rRectangle, bool bFitWidth, bool bFitHeight )
847*cdf0e10cSrcweir {
848*cdf0e10cSrcweir 	if( !mxTable.is() )
849*cdf0e10cSrcweir 		return;
850*cdf0e10cSrcweir 
851*cdf0e10cSrcweir 	const sal_Int32 nRowCount = mxTable->getRowCount();
852*cdf0e10cSrcweir 	const sal_Int32 nColCount = mxTable->getColumnCount();
853*cdf0e10cSrcweir 
854*cdf0e10cSrcweir 	if( (nRowCount != getRowCount()) || (nColCount != getColumnCount()) )
855*cdf0e10cSrcweir 	{
856*cdf0e10cSrcweir 		if( static_cast< sal_Int32 >( maRows.size() ) != nRowCount )
857*cdf0e10cSrcweir 			maRows.resize( nRowCount );
858*cdf0e10cSrcweir 
859*cdf0e10cSrcweir 		Reference< XTableRows > xRows( mxTable->getRows() );
860*cdf0e10cSrcweir 		for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
861*cdf0e10cSrcweir 			maRows[nRow].clear();
862*cdf0e10cSrcweir 
863*cdf0e10cSrcweir 		if( static_cast< sal_Int32 >( maColumns.size() ) != nColCount )
864*cdf0e10cSrcweir 			maColumns.resize( nColCount );
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir 		for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
867*cdf0e10cSrcweir 			maColumns[nCol].clear();
868*cdf0e10cSrcweir 	}
869*cdf0e10cSrcweir 
870*cdf0e10cSrcweir 	LayoutTableWidth( rRectangle, bFitWidth );
871*cdf0e10cSrcweir 	LayoutTableHeight( rRectangle, bFitHeight );
872*cdf0e10cSrcweir 	UpdateBorderLayout();
873*cdf0e10cSrcweir }
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir // -----------------------------------------------------------------------------
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir void TableLayouter::updateCells( Rectangle& rRectangle )
878*cdf0e10cSrcweir {
879*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
880*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
881*cdf0e10cSrcweir 
882*cdf0e10cSrcweir 	CellPos aPos;
883*cdf0e10cSrcweir 	for( aPos.mnRow = 0; aPos.mnRow < nRowCount; aPos.mnRow++ )
884*cdf0e10cSrcweir 	{
885*cdf0e10cSrcweir 		for( aPos.mnCol = 0; aPos.mnCol < nColCount; aPos.mnCol++ )
886*cdf0e10cSrcweir 		{
887*cdf0e10cSrcweir 			CellRef xCell( getCell( aPos ) );
888*cdf0e10cSrcweir 			if( xCell.is() )
889*cdf0e10cSrcweir 			{
890*cdf0e10cSrcweir 				basegfx::B2IRectangle aCellArea;
891*cdf0e10cSrcweir 				getCellArea( aPos, aCellArea );
892*cdf0e10cSrcweir 
893*cdf0e10cSrcweir 				Rectangle aCellRect;
894*cdf0e10cSrcweir 				aCellRect.nLeft = aCellArea.getMinX();
895*cdf0e10cSrcweir 				aCellRect.nRight = aCellArea.getMaxX();
896*cdf0e10cSrcweir 				aCellRect.nTop = aCellArea.getMinY();
897*cdf0e10cSrcweir 				aCellRect.nBottom = aCellArea.getMaxY();
898*cdf0e10cSrcweir 				aCellRect.Move( rRectangle.nLeft, rRectangle.nTop );
899*cdf0e10cSrcweir 				xCell->setCellRect( aCellRect );
900*cdf0e10cSrcweir 			}
901*cdf0e10cSrcweir 		}
902*cdf0e10cSrcweir 	}
903*cdf0e10cSrcweir }
904*cdf0e10cSrcweir 
905*cdf0e10cSrcweir // -----------------------------------------------------------------------------
906*cdf0e10cSrcweir 
907*cdf0e10cSrcweir CellRef TableLayouter::getCell( const CellPos& rPos ) const
908*cdf0e10cSrcweir {
909*cdf0e10cSrcweir 	CellRef xCell;
910*cdf0e10cSrcweir 	if( mxTable.is() ) try
911*cdf0e10cSrcweir 	{
912*cdf0e10cSrcweir 		xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ).get() ) );
913*cdf0e10cSrcweir 	}
914*cdf0e10cSrcweir 	catch( Exception& )
915*cdf0e10cSrcweir 	{
916*cdf0e10cSrcweir 		DBG_ERROR( "sdr::table::TableLayouter::getCell(), exception caught!" );
917*cdf0e10cSrcweir 	}
918*cdf0e10cSrcweir 	return xCell;
919*cdf0e10cSrcweir }
920*cdf0e10cSrcweir 
921*cdf0e10cSrcweir // -----------------------------------------------------------------------------
922*cdf0e10cSrcweir 
923*cdf0e10cSrcweir bool TableLayouter::HasPriority( const SvxBorderLine* pThis, const SvxBorderLine* pOther )
924*cdf0e10cSrcweir {
925*cdf0e10cSrcweir 	if (!pThis || ((pThis == &gEmptyBorder) && (pOther != 0)))
926*cdf0e10cSrcweir 		return false;
927*cdf0e10cSrcweir 	if (!pOther || (pOther == &gEmptyBorder))
928*cdf0e10cSrcweir 		return true;
929*cdf0e10cSrcweir 
930*cdf0e10cSrcweir 	sal_uInt16 nThisSize = pThis->GetOutWidth() + pThis->GetDistance() + pThis->GetInWidth();
931*cdf0e10cSrcweir 	sal_uInt16 nOtherSize = pOther->GetOutWidth() + pOther->GetDistance() + pOther->GetInWidth();
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir 	if (nThisSize > nOtherSize)
934*cdf0e10cSrcweir 		return true;
935*cdf0e10cSrcweir 
936*cdf0e10cSrcweir 	else if (nThisSize < nOtherSize)
937*cdf0e10cSrcweir 	{
938*cdf0e10cSrcweir 		return false;
939*cdf0e10cSrcweir 	}
940*cdf0e10cSrcweir 	else
941*cdf0e10cSrcweir 	{
942*cdf0e10cSrcweir 		if ( pOther->GetInWidth() && !pThis->GetInWidth() )
943*cdf0e10cSrcweir 		{
944*cdf0e10cSrcweir 			return true;
945*cdf0e10cSrcweir 		}
946*cdf0e10cSrcweir 		else if ( pThis->GetInWidth() && !pOther->GetInWidth() )
947*cdf0e10cSrcweir 		{
948*cdf0e10cSrcweir 			return false;
949*cdf0e10cSrcweir 		}
950*cdf0e10cSrcweir 		else
951*cdf0e10cSrcweir 		{
952*cdf0e10cSrcweir 			return true;			//! ???
953*cdf0e10cSrcweir 		}
954*cdf0e10cSrcweir 	}
955*cdf0e10cSrcweir }
956*cdf0e10cSrcweir 
957*cdf0e10cSrcweir // -----------------------------------------------------------------------------
958*cdf0e10cSrcweir 
959*cdf0e10cSrcweir void TableLayouter::SetBorder( sal_Int32 nCol, sal_Int32 nRow, bool bHorizontal, const SvxBorderLine* pLine )
960*cdf0e10cSrcweir {
961*cdf0e10cSrcweir 	if( pLine == 0 )
962*cdf0e10cSrcweir 		pLine = &gEmptyBorder;
963*cdf0e10cSrcweir 
964*cdf0e10cSrcweir 	SvxBorderLine *pOld = bHorizontal ? maHorizontalBorders[nCol][nRow] : maVerticalBorders[nCol][nRow];
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir 	if( HasPriority( pLine, pOld ) )
967*cdf0e10cSrcweir 	{
968*cdf0e10cSrcweir 		if( (pOld != 0) && (pOld != &gEmptyBorder) )
969*cdf0e10cSrcweir 			delete pOld;
970*cdf0e10cSrcweir 
971*cdf0e10cSrcweir 		SvxBorderLine* pNew = ( pLine != &gEmptyBorder ) ?  new SvxBorderLine(*pLine) : &gEmptyBorder;
972*cdf0e10cSrcweir 
973*cdf0e10cSrcweir 		if( bHorizontal )
974*cdf0e10cSrcweir 			maHorizontalBorders[nCol][nRow] = pNew;
975*cdf0e10cSrcweir 		else
976*cdf0e10cSrcweir 			maVerticalBorders[nCol][nRow]  = pNew;
977*cdf0e10cSrcweir 	}
978*cdf0e10cSrcweir }
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir // -----------------------------------------------------------------------------
981*cdf0e10cSrcweir 
982*cdf0e10cSrcweir void TableLayouter::ClearBorderLayout()
983*cdf0e10cSrcweir {
984*cdf0e10cSrcweir 	ClearBorderLayout(maHorizontalBorders);
985*cdf0e10cSrcweir 	ClearBorderLayout(maVerticalBorders);
986*cdf0e10cSrcweir }
987*cdf0e10cSrcweir 
988*cdf0e10cSrcweir // -----------------------------------------------------------------------------
989*cdf0e10cSrcweir 
990*cdf0e10cSrcweir void TableLayouter::ClearBorderLayout(BorderLineMap& rMap)
991*cdf0e10cSrcweir {
992*cdf0e10cSrcweir 	const sal_Int32 nColCount = rMap.size();
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir 	for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
995*cdf0e10cSrcweir 	{
996*cdf0e10cSrcweir 		const sal_Int32 nRowCount = rMap[nCol].size();
997*cdf0e10cSrcweir 		for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
998*cdf0e10cSrcweir 		{
999*cdf0e10cSrcweir 			SvxBorderLine* pLine = rMap[nCol][nRow];
1000*cdf0e10cSrcweir 			if( pLine )
1001*cdf0e10cSrcweir 			{
1002*cdf0e10cSrcweir 				if( pLine != &gEmptyBorder )
1003*cdf0e10cSrcweir 					delete pLine;
1004*cdf0e10cSrcweir 
1005*cdf0e10cSrcweir 				rMap[nCol][nRow] = 0;
1006*cdf0e10cSrcweir 			}
1007*cdf0e10cSrcweir 		}
1008*cdf0e10cSrcweir 	}
1009*cdf0e10cSrcweir }
1010*cdf0e10cSrcweir 
1011*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir void TableLayouter::ResizeBorderLayout()
1014*cdf0e10cSrcweir {
1015*cdf0e10cSrcweir 	ClearBorderLayout();
1016*cdf0e10cSrcweir 	ResizeBorderLayout(maHorizontalBorders);
1017*cdf0e10cSrcweir 	ResizeBorderLayout(maVerticalBorders);
1018*cdf0e10cSrcweir }
1019*cdf0e10cSrcweir 
1020*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1021*cdf0e10cSrcweir 
1022*cdf0e10cSrcweir void TableLayouter::ResizeBorderLayout( BorderLineMap& rMap )
1023*cdf0e10cSrcweir {
1024*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount() + 1;
1025*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount() + 1;
1026*cdf0e10cSrcweir 
1027*cdf0e10cSrcweir 	if( sal::static_int_cast<sal_Int32>(rMap.size()) != nColCount )
1028*cdf0e10cSrcweir 		rMap.resize( nColCount );
1029*cdf0e10cSrcweir 
1030*cdf0e10cSrcweir 	for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
1031*cdf0e10cSrcweir 	{
1032*cdf0e10cSrcweir 		if( sal::static_int_cast<sal_Int32>(rMap[nCol].size()) != nRowCount )
1033*cdf0e10cSrcweir 			rMap[nCol].resize( nRowCount );
1034*cdf0e10cSrcweir 	}
1035*cdf0e10cSrcweir }
1036*cdf0e10cSrcweir 
1037*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1038*cdf0e10cSrcweir 
1039*cdf0e10cSrcweir void TableLayouter::UpdateBorderLayout()
1040*cdf0e10cSrcweir {
1041*cdf0e10cSrcweir 	// make sure old border layout is cleared and border maps have correct size
1042*cdf0e10cSrcweir 	ResizeBorderLayout();
1043*cdf0e10cSrcweir 
1044*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
1045*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
1046*cdf0e10cSrcweir 
1047*cdf0e10cSrcweir 	CellPos aPos;
1048*cdf0e10cSrcweir 	for( aPos.mnRow = 0; aPos.mnRow < nRowCount; aPos.mnRow++ )
1049*cdf0e10cSrcweir 	{
1050*cdf0e10cSrcweir 		for( aPos.mnCol = 0; aPos.mnCol < nColCount; aPos.mnCol++ )
1051*cdf0e10cSrcweir 		{
1052*cdf0e10cSrcweir 			CellRef xCell( getCell( aPos ) );
1053*cdf0e10cSrcweir 			if( !xCell.is() || xCell->isMerged() )
1054*cdf0e10cSrcweir 				continue;
1055*cdf0e10cSrcweir 
1056*cdf0e10cSrcweir 			const SvxBoxItem* pThisAttr = (const SvxBoxItem*)xCell->GetItemSet().GetItem( SDRATTR_TABLE_BORDER );
1057*cdf0e10cSrcweir 			OSL_ENSURE(pThisAttr,"sdr::table::TableLayouter::UpdateBorderLayout(), no border attribute?");
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir 			if( !pThisAttr )
1060*cdf0e10cSrcweir 				continue;
1061*cdf0e10cSrcweir 
1062*cdf0e10cSrcweir 			const sal_Int32 nLastRow = xCell->getRowSpan() + aPos.mnRow;
1063*cdf0e10cSrcweir 			const sal_Int32 nLastCol = xCell->getColumnSpan() + aPos.mnCol;
1064*cdf0e10cSrcweir 
1065*cdf0e10cSrcweir 			for( sal_Int32 nRow = aPos.mnRow; nRow < nLastRow; nRow++ )
1066*cdf0e10cSrcweir 			{
1067*cdf0e10cSrcweir 				SetBorder( aPos.mnCol, nRow, false, pThisAttr->GetLeft() );
1068*cdf0e10cSrcweir 				SetBorder( nLastCol, nRow, false, pThisAttr->GetRight() );
1069*cdf0e10cSrcweir 			}
1070*cdf0e10cSrcweir 
1071*cdf0e10cSrcweir 			for( sal_Int32 nCol = aPos.mnCol; nCol < nLastCol; nCol++ )
1072*cdf0e10cSrcweir 			{
1073*cdf0e10cSrcweir 				SetBorder( nCol, aPos.mnRow, true, pThisAttr->GetTop() );
1074*cdf0e10cSrcweir 				SetBorder( nCol, nLastRow, true, pThisAttr->GetBottom() );
1075*cdf0e10cSrcweir 			}
1076*cdf0e10cSrcweir 		}
1077*cdf0e10cSrcweir 	}
1078*cdf0e10cSrcweir }
1079*cdf0e10cSrcweir 
1080*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1081*cdf0e10cSrcweir /*
1082*cdf0e10cSrcweir void TableLayouter::SetLayoutToModel()
1083*cdf0e10cSrcweir {
1084*cdf0e10cSrcweir 	const sal_Int32 nRowCount = getRowCount();
1085*cdf0e10cSrcweir 	const sal_Int32 nColCount = getColumnCount();
1086*cdf0e10cSrcweir 
1087*cdf0e10cSrcweir 	try
1088*cdf0e10cSrcweir 	{
1089*cdf0e10cSrcweir 		sal_Int32 nOldSize = 0;
1090*cdf0e10cSrcweir 
1091*cdf0e10cSrcweir 		Reference< XIndexAccess > xRows( mxTable->getRows(), UNO_QUERY_THROW );
1092*cdf0e10cSrcweir 		for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
1093*cdf0e10cSrcweir 		{
1094*cdf0e10cSrcweir 			Reference< XPropertySet > xRowSet( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
1095*cdf0e10cSrcweir 			xRowSet->getPropertyValue( msSize ) >>= nOldSize;
1096*cdf0e10cSrcweir 			if( maRows[nRow].mnSize != nOldSize )
1097*cdf0e10cSrcweir 				xRowSet->setPropertyValue( msSize, Any( maRows[nRow].mnSize )  );
1098*cdf0e10cSrcweir 		}
1099*cdf0e10cSrcweir 
1100*cdf0e10cSrcweir 		for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ )
1101*cdf0e10cSrcweir 		{
1102*cdf0e10cSrcweir 			Reference< XPropertySet > xColSet( getColumnByIndex( nCol ), UNO_QUERY_THROW );
1103*cdf0e10cSrcweir 			xColSet->getPropertyValue( msSize ) >>= nOldSize;
1104*cdf0e10cSrcweir 			if( maColumns[nCol].mnSize != nOldSize )
1105*cdf0e10cSrcweir 				xColSet->setPropertyValue( msSize, Any( maColumns[nCol].mnSize )  );
1106*cdf0e10cSrcweir 		}
1107*cdf0e10cSrcweir 	}
1108*cdf0e10cSrcweir 	catch( Exception& )
1109*cdf0e10cSrcweir 	{
1110*cdf0e10cSrcweir 		DBG_ERROR("sdr::table::TableLayouter::SetLayoutToModel(), exception caught!");
1111*cdf0e10cSrcweir 	}
1112*cdf0e10cSrcweir }
1113*cdf0e10cSrcweir */
1114*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1115*cdf0e10cSrcweir 
1116*cdf0e10cSrcweir void TableLayouter::DistributeColumns( ::Rectangle& rArea, sal_Int32 nFirstCol, sal_Int32 nLastCol )
1117*cdf0e10cSrcweir {
1118*cdf0e10cSrcweir 	if( mxTable.is() ) try
1119*cdf0e10cSrcweir 	{
1120*cdf0e10cSrcweir 		const sal_Int32 nColCount = getColumnCount();
1121*cdf0e10cSrcweir 
1122*cdf0e10cSrcweir 		if( (nFirstCol < 0) || (nFirstCol>= nLastCol) || (nLastCol >= nColCount) )
1123*cdf0e10cSrcweir 			return;
1124*cdf0e10cSrcweir 
1125*cdf0e10cSrcweir 		sal_Int32 nAllWidth = 0;
1126*cdf0e10cSrcweir 		for( sal_Int32 nCol = nFirstCol; nCol <= nLastCol; ++nCol )
1127*cdf0e10cSrcweir 			nAllWidth += getColumnWidth(nCol);
1128*cdf0e10cSrcweir 
1129*cdf0e10cSrcweir 		sal_Int32 nWidth = nAllWidth / (nLastCol-nFirstCol+1);
1130*cdf0e10cSrcweir 
1131*cdf0e10cSrcweir 		Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
1132*cdf0e10cSrcweir 
1133*cdf0e10cSrcweir 		for( sal_Int32 nCol = nFirstCol; nCol <= nLastCol; ++nCol )
1134*cdf0e10cSrcweir 		{
1135*cdf0e10cSrcweir 			if( nCol == nLastCol )
1136*cdf0e10cSrcweir 				nWidth = nAllWidth; // last column get round errors
1137*cdf0e10cSrcweir 
1138*cdf0e10cSrcweir 			Reference< XPropertySet > xColSet( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
1139*cdf0e10cSrcweir 			xColSet->setPropertyValue( msSize, Any( nWidth ) );
1140*cdf0e10cSrcweir 
1141*cdf0e10cSrcweir 			nAllWidth -= nWidth;
1142*cdf0e10cSrcweir 		}
1143*cdf0e10cSrcweir 
1144*cdf0e10cSrcweir 		LayoutTable( rArea, true, false );
1145*cdf0e10cSrcweir 	}
1146*cdf0e10cSrcweir 	catch( Exception& e )
1147*cdf0e10cSrcweir 	{
1148*cdf0e10cSrcweir 		(void)e;
1149*cdf0e10cSrcweir 		DBG_ERROR("sdr::table::TableLayouter::DistributeColumns(), exception caught!");
1150*cdf0e10cSrcweir 	}
1151*cdf0e10cSrcweir }
1152*cdf0e10cSrcweir 
1153*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1154*cdf0e10cSrcweir 
1155*cdf0e10cSrcweir void TableLayouter::DistributeRows( ::Rectangle& rArea, sal_Int32 nFirstRow, sal_Int32 nLastRow )
1156*cdf0e10cSrcweir {
1157*cdf0e10cSrcweir 	if( mxTable.is() ) try
1158*cdf0e10cSrcweir 	{
1159*cdf0e10cSrcweir 		const sal_Int32 nRowCount = mxTable->getRowCount();
1160*cdf0e10cSrcweir 
1161*cdf0e10cSrcweir 		if( (nFirstRow < 0) || (nFirstRow>= nLastRow) || (nLastRow >= nRowCount) )
1162*cdf0e10cSrcweir 			return;
1163*cdf0e10cSrcweir 
1164*cdf0e10cSrcweir 		sal_Int32 nAllHeight = 0;
1165*cdf0e10cSrcweir 		sal_Int32 nMinHeight = 0;
1166*cdf0e10cSrcweir 
1167*cdf0e10cSrcweir 		for( sal_Int32 nRow = nFirstRow; nRow <= nLastRow; ++nRow )
1168*cdf0e10cSrcweir 		{
1169*cdf0e10cSrcweir 			nMinHeight = std::max( maRows[nRow].mnMinSize, nMinHeight );
1170*cdf0e10cSrcweir 			nAllHeight += maRows[nRow].mnSize;
1171*cdf0e10cSrcweir 		}
1172*cdf0e10cSrcweir 
1173*cdf0e10cSrcweir 		const sal_Int32 nRows = (nLastRow-nFirstRow+1);
1174*cdf0e10cSrcweir 		sal_Int32 nHeight = nAllHeight / nRows;
1175*cdf0e10cSrcweir 
1176*cdf0e10cSrcweir 		if( nHeight < nMinHeight )
1177*cdf0e10cSrcweir 		{
1178*cdf0e10cSrcweir 			sal_Int32 nNeededHeight = nRows * nMinHeight;
1179*cdf0e10cSrcweir 			rArea.nBottom += nNeededHeight - nAllHeight;
1180*cdf0e10cSrcweir 			nHeight = nMinHeight;
1181*cdf0e10cSrcweir 			nAllHeight = nRows * nMinHeight;
1182*cdf0e10cSrcweir 		}
1183*cdf0e10cSrcweir 
1184*cdf0e10cSrcweir 		Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
1185*cdf0e10cSrcweir 		for( sal_Int32 nRow = nFirstRow; nRow <= nLastRow; ++nRow )
1186*cdf0e10cSrcweir 		{
1187*cdf0e10cSrcweir 			if( nRow == nLastRow )
1188*cdf0e10cSrcweir 				nHeight = nAllHeight; // last row get round errors
1189*cdf0e10cSrcweir 
1190*cdf0e10cSrcweir 			Reference< XPropertySet > xRowSet( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
1191*cdf0e10cSrcweir 			xRowSet->setPropertyValue( msSize, Any( nHeight ) );
1192*cdf0e10cSrcweir 
1193*cdf0e10cSrcweir 			nAllHeight -= nHeight;
1194*cdf0e10cSrcweir 		}
1195*cdf0e10cSrcweir 
1196*cdf0e10cSrcweir 		LayoutTable( rArea, false, true );
1197*cdf0e10cSrcweir 	}
1198*cdf0e10cSrcweir 	catch( Exception& e )
1199*cdf0e10cSrcweir 	{
1200*cdf0e10cSrcweir 		(void)e;
1201*cdf0e10cSrcweir 		DBG_ERROR("sdr::table::TableLayouter::DistributeRows(), exception caught!");
1202*cdf0e10cSrcweir 	}
1203*cdf0e10cSrcweir }
1204*cdf0e10cSrcweir 
1205*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1206*cdf0e10cSrcweir 
1207*cdf0e10cSrcweir void TableLayouter::SetWritingMode( com::sun::star::text::WritingMode eWritingMode )
1208*cdf0e10cSrcweir {
1209*cdf0e10cSrcweir 	meWritingMode = eWritingMode;
1210*cdf0e10cSrcweir }
1211*cdf0e10cSrcweir 
1212*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1213*cdf0e10cSrcweir 
1214*cdf0e10cSrcweir sal_Int32 TableLayouter::getColumnStart( sal_Int32 nColumn ) const
1215*cdf0e10cSrcweir {
1216*cdf0e10cSrcweir 	if( isValidColumn(nColumn) )
1217*cdf0e10cSrcweir 		return maColumns[nColumn].mnPos;
1218*cdf0e10cSrcweir 	else
1219*cdf0e10cSrcweir 		return 0;
1220*cdf0e10cSrcweir }
1221*cdf0e10cSrcweir 
1222*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1223*cdf0e10cSrcweir 
1224*cdf0e10cSrcweir sal_Int32 TableLayouter::getRowStart( sal_Int32 nRow ) const
1225*cdf0e10cSrcweir {
1226*cdf0e10cSrcweir 	if( isValidRow(nRow) )
1227*cdf0e10cSrcweir 		return maRows[nRow].mnPos;
1228*cdf0e10cSrcweir 	else
1229*cdf0e10cSrcweir 		return 0;
1230*cdf0e10cSrcweir }
1231*cdf0e10cSrcweir 
1232*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1233*cdf0e10cSrcweir 
1234*cdf0e10cSrcweir /*
1235*cdf0e10cSrcweir sal_Int32 TableLayouter::detectInsertedOrRemovedRows()
1236*cdf0e10cSrcweir {
1237*cdf0e10cSrcweir 	sal_Int32 nHeightChange = 0;
1238*cdf0e10cSrcweir 
1239*cdf0e10cSrcweir 	try
1240*cdf0e10cSrcweir 	{
1241*cdf0e10cSrcweir 		Reference< XIndexAccess > xRows( mxTable->getRows(), UNO_QUERY_THROW );
1242*cdf0e10cSrcweir 		std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > >::iterator oldIter( mxRows.begin() );
1243*cdf0e10cSrcweir 		sal_Int32 nCount = xRows->getCount();
1244*cdf0e10cSrcweir 		for( sal_Int32 nRow = 0; nRow < nCount; nRow++ )
1245*cdf0e10cSrcweir 		{
1246*cdf0e10cSrcweir 			Reference< XInterface > xRow( xRows->getByIndex(nRow), UNO_QUERY );
1247*cdf0e10cSrcweir 
1248*cdf0e10cSrcweir 			std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > >::iterator searchIter = mxRows.end();
1249*cdf0e10cSrcweir 			if( oldIter != mxRows.end() )
1250*cdf0e10cSrcweir 				searchIter = std::find( oldIter,mxRows.end(), xRow );
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir 			if( searchIter == mxRows.end() )
1253*cdf0e10cSrcweir 			{
1254*cdf0e10cSrcweir 				// new row
1255*cdf0e10cSrcweir 				Reference< XPropertySet > xSet( xRow, UNO_QUERY_THROW );
1256*cdf0e10cSrcweir 				sal_Int32 nSize = 0;
1257*cdf0e10cSrcweir 				xSet->getPropertyValue( msSize ) >>= nSize;
1258*cdf0e10cSrcweir 				nHeightChange += nSize;
1259*cdf0e10cSrcweir 			}
1260*cdf0e10cSrcweir 			else if( searchIter == oldIter )
1261*cdf0e10cSrcweir 			{
1262*cdf0e10cSrcweir 				// no change
1263*cdf0e10cSrcweir 				oldIter++;
1264*cdf0e10cSrcweir 			}
1265*cdf0e10cSrcweir 			else
1266*cdf0e10cSrcweir 			{
1267*cdf0e10cSrcweir 				// rows removed
1268*cdf0e10cSrcweir 				do
1269*cdf0e10cSrcweir 				{
1270*cdf0e10cSrcweir 					Reference< XPropertySet > xSet( (*oldIter), UNO_QUERY_THROW );
1271*cdf0e10cSrcweir 					sal_Int32 nSize = 0;
1272*cdf0e10cSrcweir 					xSet->getPropertyValue( msSize ) >>= nSize;
1273*cdf0e10cSrcweir 					nHeightChange -= nSize;
1274*cdf0e10cSrcweir 				}
1275*cdf0e10cSrcweir 				while( oldIter++ != searchIter );
1276*cdf0e10cSrcweir 			}
1277*cdf0e10cSrcweir 		}
1278*cdf0e10cSrcweir 
1279*cdf0e10cSrcweir 		while( oldIter != mxRows.end() )
1280*cdf0e10cSrcweir 		{
1281*cdf0e10cSrcweir 			// rows removed
1282*cdf0e10cSrcweir 			Reference< XPropertySet > xSet( (*oldIter++), UNO_QUERY_THROW );
1283*cdf0e10cSrcweir 			sal_Int32 nSize = 0;
1284*cdf0e10cSrcweir 			xSet->getPropertyValue( msSize ) >>= nSize;
1285*cdf0e10cSrcweir 			nHeightChange -= nSize;
1286*cdf0e10cSrcweir 		}
1287*cdf0e10cSrcweir 	}
1288*cdf0e10cSrcweir 	catch( Exception& e )
1289*cdf0e10cSrcweir 	{
1290*cdf0e10cSrcweir 		(void)e;
1291*cdf0e10cSrcweir 		DBG_ERROR("svx::TableLayouter::detectInsertedOrRemovedRows(), exception caught!");
1292*cdf0e10cSrcweir 	}
1293*cdf0e10cSrcweir 
1294*cdf0e10cSrcweir 	return nHeightChange;
1295*cdf0e10cSrcweir }
1296*cdf0e10cSrcweir */
1297*cdf0e10cSrcweir 
1298*cdf0e10cSrcweir // -----------------------------------------------------------------------------
1299*cdf0e10cSrcweir 
1300*cdf0e10cSrcweir } }
1301