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