LCOV - code coverage report
Current view: top level - svx/source/table - tablelayouter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 309 520 59.4 %
Date: 2015-06-13 12:38:46 Functions: 20 31 64.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11