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