merge the formfield patch from ooo-build
[ooovba.git] / toolkit / source / layout / core / table.cxx
blob2beefc1709382e23cd9f8e1d602a389eea264bf9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile$
11 * $Revision$
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include <table.hxx>
34 #include <sal/macros.h>
35 #include <osl/mutex.hxx>
36 #include <cppuhelper/propshlp.hxx>
37 #include <cppuhelper/interfacecontainer.h>
38 #include <com/sun/star/awt/PosSize.hpp>
39 #include <tools/debug.hxx>
41 // fixed point precision for distributing error
42 #define FIXED_PT 16
44 namespace layoutimpl
47 using namespace com::sun::star;
49 Table::ChildProps::ChildProps( Table::ChildData *pData )
51 addProp( RTL_CONSTASCII_USTRINGPARAM( "XExpand" ),
52 ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
53 &( pData->mbExpand[ 0 ] ) );
54 addProp( RTL_CONSTASCII_USTRINGPARAM( "YExpand" ),
55 ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
56 &( pData->mbExpand[ 1 ] ) );
57 addProp( RTL_CONSTASCII_USTRINGPARAM( "ColSpan" ),
58 ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
59 &( pData->mnColSpan ) );
60 addProp( RTL_CONSTASCII_USTRINGPARAM( "RowSpan" ),
61 ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
62 &( pData->mnRowSpan ) );
65 bool Table::ChildData::isVisible()
67 return Box_Base::ChildData::isVisible()
68 && ( mnColSpan > 0 ) && ( mnRowSpan > 0 );
71 Table::Table()
72 : Box_Base()
73 , mnColsLen( 1 )// another default value could be 0xffff for infinite columns( = 1 row )
75 addProp( RTL_CONSTASCII_USTRINGPARAM( "Columns" ),
76 ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
77 &mnColsLen );
80 Table::ChildData::ChildData( uno::Reference< awt::XLayoutConstrains > const& xChild )
81 : Box_Base::ChildData( xChild )
82 // , mbExpand( { 1, 1 } )
83 , mnColSpan( 1 )
84 , mnRowSpan( 1 )
85 , mnLeftCol( 0 )
86 , mnRightCol( 0 )
87 , mnTopRow( 0 )
88 , mnBottomRow( 0 )
90 mbExpand[ 0 ] = 1;
91 mbExpand[ 1 ] = 1;
94 Table::ChildData*
95 Table::createChild( uno::Reference< awt::XLayoutConstrains > const& xChild )
97 return new ChildData( xChild );
100 Table::ChildProps*
101 Table::createChildProps( Box_Base::ChildData *pData )
103 return new ChildProps( static_cast<Table::ChildData*> ( pData ) );
106 void SAL_CALL
107 Table::addChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
108 throw( uno::RuntimeException, awt::MaxChildrenException )
110 if ( xChild.is() )
112 Box_Base::addChild( xChild );
113 // cause of flicker
114 allocateChildAt( xChild, awt::Rectangle( 0,0,0,0 ) );
118 awt::Size SAL_CALL
119 Table::getMinimumSize() throw( uno::RuntimeException )
121 int nRowsLen = 0;
123 // 1. layout the table -- adjust to cope with row-spans...
125 // temporary 1D representation of the table
126 std::vector< ChildData *> aTable;
128 int col = 0;
129 int row = 0;
130 for ( std::list<Box_Base::ChildData *>::iterator it
131 = maChildren.begin(); it != maChildren.end(); it++ )
133 ChildData *child = static_cast<Table::ChildData*> ( *it );
134 if ( !child->isVisible() )
135 continue;
137 while ( col + SAL_MIN( child->mnColSpan, mnColsLen ) > mnColsLen )
139 col = 0;
140 row++;
142 unsigned int i = col +( row*mnColsLen );
143 while ( aTable.size() > i && !aTable[ i ] )
144 i++;
146 col = i % mnColsLen;
147 row = i / mnColsLen;
150 child->mnLeftCol = col;
151 child->mnRightCol = SAL_MIN( col + child->mnColSpan, mnColsLen );
152 child->mnTopRow = row;
153 child->mnBottomRow = row + child->mnRowSpan;
155 col += child->mnColSpan;
157 unsigned int start = child->mnLeftCol +( child->mnTopRow*mnColsLen );
158 unsigned int end =( child->mnRightCol-1 ) +( ( child->mnBottomRow-1 )*mnColsLen );
159 if ( aTable.size() < end+1 )
160 aTable.resize( end+1, NULL );
161 for ( unsigned int i = start; i < end; i++ )
162 aTable[ i ] = child;
164 nRowsLen = SAL_MAX( nRowsLen, child->mnBottomRow );
168 // 2. calculate columns/rows sizes
169 for ( int g = 0; g < 2; g++ )
171 std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
173 aGroup.clear();
174 aGroup.resize( g == 0 ? mnColsLen : nRowsLen );
176 // 2.1 base sizes on one-column/row children
177 for ( std::list<Box_Base::ChildData *>::iterator it
178 = maChildren.begin(); it != maChildren.end(); it++ )
180 ChildData *child = static_cast<Table::ChildData*> ( *it );
181 if ( !child->isVisible() )
182 continue;
183 const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
184 const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
186 if ( nFirstAttach == nLastAttach-1 )
188 child->maRequisition = child->mxChild->getMinimumSize();
189 int attach = nFirstAttach;
190 int child_size = g == 0 ? child->maRequisition.Width
191 : child->maRequisition.Height;
192 aGroup[ attach ].mnSize = SAL_MAX( aGroup[ attach ].mnSize,
193 child_size );
194 if ( child->mbExpand[ g ] )
195 aGroup[ attach ].mbExpand = true;
199 // 2.2 make sure multiple-columns/rows children fit
200 for ( std::list<Box_Base::ChildData *>::iterator it
201 = maChildren.begin(); it != maChildren.end(); it++ )
203 ChildData *child = static_cast<Table::ChildData*> ( *it );
204 if ( !child->isVisible() )
205 continue;
206 const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
207 const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
209 if ( nFirstAttach != nLastAttach-1 )
211 child->maRequisition = child->mxChild->getMinimumSize();
212 int size = 0;
213 int expandables = 0;
214 for ( int i = nFirstAttach; i < nLastAttach; i++ )
216 size += aGroup[ i ].mnSize;
217 if ( aGroup[ i ].mbExpand )
218 expandables++;
221 int child_size = g == 0 ? child->maRequisition.Width
222 : child->maRequisition.Height;
223 int extra = child_size - size;
224 if ( extra > 0 )
226 if ( expandables )
227 extra /= expandables;
228 else
229 extra /= nLastAttach - nFirstAttach;
231 for ( int i = nFirstAttach; i < nLastAttach; i++ )
232 if ( expandables == 0 || aGroup[ i ].mbExpand )
233 aGroup[ i ].mnSize += extra;
239 // 3. Sum everything up
240 mnColExpandables =( mnRowExpandables = 0 );
241 maRequisition.Width =( maRequisition.Height = 0 );
242 for ( std::vector<GroupData>::iterator it = maCols.begin();
243 it != maCols.end(); it++ )
245 maRequisition.Width += it->mnSize;
246 if ( it->mbExpand )
247 mnColExpandables++;
249 for ( std::vector<GroupData>::iterator it = maRows.begin();
250 it != maRows.end(); it++ )
252 maRequisition.Height += it->mnSize;
253 if ( it->mbExpand )
254 mnRowExpandables++;
257 return maRequisition;
260 void SAL_CALL
261 Table::allocateArea( const awt::Rectangle &rArea )
262 throw( uno::RuntimeException )
264 maAllocation = rArea;
265 if ( maCols.size() == 0 || maRows.size() == 0 )
266 return;
268 int nExtraSize[ 2 ] = { SAL_MAX( rArea.Width - maRequisition.Width, 0 ),
269 SAL_MAX( rArea.Height - maRequisition.Height, 0 ) };
270 // split it
271 nExtraSize[ 0 ] /= mnColExpandables ? mnColExpandables : mnColsLen;
272 nExtraSize[ 1 ] /= mnRowExpandables ? mnRowExpandables : maRows.size();
274 for ( std::list<Box_Base::ChildData *>::const_iterator it
275 = maChildren.begin(); it != maChildren.end(); it++ )
277 ChildData *child = static_cast<Table::ChildData*> ( *it );
278 if ( !child->isVisible() )
279 continue;
281 awt::Rectangle rChildArea( rArea.X, rArea.Y, 0, 0 );
283 for ( int g = 0; g < 2; g++ )
285 std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
286 const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
287 const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
289 for ( int i = 0; i < nFirstAttach; i++ )
291 int gSize = aGroup[ i ].mnSize;
292 if ( aGroup[ i ].mbExpand )
293 gSize += nExtraSize[ g ];
294 if ( g == 0 )
295 rChildArea.X += gSize;
296 else
297 rChildArea.Y += gSize;
299 for ( int i = nFirstAttach; i < nLastAttach; i++ )
301 int gSize = aGroup[ i ].mnSize;
302 if ( aGroup[ i ].mbExpand )
303 gSize += nExtraSize[ g ];
304 if ( g == 0 )
305 rChildArea.Width += gSize;
306 else
307 rChildArea.Height += gSize;
311 allocateChildAt( child->mxChild, rChildArea );
315 } // namespace layoutimpl