xref: /trunk/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