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

Generated by: LCOV version 1.10