1*b0724fc6SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*b0724fc6SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*b0724fc6SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*b0724fc6SAndrew Rist * distributed with this work for additional information
6*b0724fc6SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*b0724fc6SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*b0724fc6SAndrew Rist * "License"); you may not use this file except in compliance
9*b0724fc6SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*b0724fc6SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*b0724fc6SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*b0724fc6SAndrew Rist * software distributed under the License is distributed on an
15*b0724fc6SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b0724fc6SAndrew Rist * KIND, either express or implied. See the License for the
17*b0724fc6SAndrew Rist * specific language governing permissions and limitations
18*b0724fc6SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*b0724fc6SAndrew Rist *************************************************************/
21*b0724fc6SAndrew Rist
22*b0724fc6SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #include <table.hxx>
25cdf0e10cSrcweir
26cdf0e10cSrcweir #include <sal/macros.h>
27cdf0e10cSrcweir #include <osl/mutex.hxx>
28cdf0e10cSrcweir #include <cppuhelper/propshlp.hxx>
29cdf0e10cSrcweir #include <cppuhelper/interfacecontainer.h>
30cdf0e10cSrcweir #include <com/sun/star/awt/PosSize.hpp>
31cdf0e10cSrcweir #include <tools/debug.hxx>
32cdf0e10cSrcweir
33cdf0e10cSrcweir // fixed point precision for distributing error
34cdf0e10cSrcweir #define FIXED_PT 16
35cdf0e10cSrcweir
36cdf0e10cSrcweir namespace layoutimpl
37cdf0e10cSrcweir {
38cdf0e10cSrcweir
39cdf0e10cSrcweir using namespace com::sun::star;
40cdf0e10cSrcweir
ChildProps(Table::ChildData * pData)41cdf0e10cSrcweir Table::ChildProps::ChildProps( Table::ChildData *pData )
42cdf0e10cSrcweir {
43cdf0e10cSrcweir addProp( RTL_CONSTASCII_USTRINGPARAM( "XExpand" ),
44cdf0e10cSrcweir ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
45cdf0e10cSrcweir &( pData->mbExpand[ 0 ] ) );
46cdf0e10cSrcweir addProp( RTL_CONSTASCII_USTRINGPARAM( "YExpand" ),
47cdf0e10cSrcweir ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
48cdf0e10cSrcweir &( pData->mbExpand[ 1 ] ) );
49cdf0e10cSrcweir addProp( RTL_CONSTASCII_USTRINGPARAM( "ColSpan" ),
50cdf0e10cSrcweir ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
51cdf0e10cSrcweir &( pData->mnColSpan ) );
52cdf0e10cSrcweir addProp( RTL_CONSTASCII_USTRINGPARAM( "RowSpan" ),
53cdf0e10cSrcweir ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
54cdf0e10cSrcweir &( pData->mnRowSpan ) );
55cdf0e10cSrcweir }
56cdf0e10cSrcweir
isVisible()57cdf0e10cSrcweir bool Table::ChildData::isVisible()
58cdf0e10cSrcweir {
59cdf0e10cSrcweir return Box_Base::ChildData::isVisible()
60cdf0e10cSrcweir && ( mnColSpan > 0 ) && ( mnRowSpan > 0 );
61cdf0e10cSrcweir }
62cdf0e10cSrcweir
Table()63cdf0e10cSrcweir Table::Table()
64cdf0e10cSrcweir : Box_Base()
65cdf0e10cSrcweir , mnColsLen( 1 )// another default value could be 0xffff for infinite columns( = 1 row )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir addProp( RTL_CONSTASCII_USTRINGPARAM( "Columns" ),
68cdf0e10cSrcweir ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
69cdf0e10cSrcweir &mnColsLen );
70cdf0e10cSrcweir }
71cdf0e10cSrcweir
ChildData(uno::Reference<awt::XLayoutConstrains> const & xChild)72cdf0e10cSrcweir Table::ChildData::ChildData( uno::Reference< awt::XLayoutConstrains > const& xChild )
73cdf0e10cSrcweir : Box_Base::ChildData( xChild )
74cdf0e10cSrcweir // , mbExpand( { 1, 1 } )
75cdf0e10cSrcweir , mnColSpan( 1 )
76cdf0e10cSrcweir , mnRowSpan( 1 )
77cdf0e10cSrcweir , mnLeftCol( 0 )
78cdf0e10cSrcweir , mnRightCol( 0 )
79cdf0e10cSrcweir , mnTopRow( 0 )
80cdf0e10cSrcweir , mnBottomRow( 0 )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir mbExpand[ 0 ] = 1;
83cdf0e10cSrcweir mbExpand[ 1 ] = 1;
84cdf0e10cSrcweir }
85cdf0e10cSrcweir
86cdf0e10cSrcweir Table::ChildData*
createChild(uno::Reference<awt::XLayoutConstrains> const & xChild)87cdf0e10cSrcweir Table::createChild( uno::Reference< awt::XLayoutConstrains > const& xChild )
88cdf0e10cSrcweir {
89cdf0e10cSrcweir return new ChildData( xChild );
90cdf0e10cSrcweir }
91cdf0e10cSrcweir
92cdf0e10cSrcweir Table::ChildProps*
createChildProps(Box_Base::ChildData * pData)93cdf0e10cSrcweir Table::createChildProps( Box_Base::ChildData *pData )
94cdf0e10cSrcweir {
95cdf0e10cSrcweir return new ChildProps( static_cast<Table::ChildData*> ( pData ) );
96cdf0e10cSrcweir }
97cdf0e10cSrcweir
98cdf0e10cSrcweir void SAL_CALL
addChild(const uno::Reference<awt::XLayoutConstrains> & xChild)99cdf0e10cSrcweir Table::addChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
100cdf0e10cSrcweir throw( uno::RuntimeException, awt::MaxChildrenException )
101cdf0e10cSrcweir {
102cdf0e10cSrcweir if ( xChild.is() )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir Box_Base::addChild( xChild );
105cdf0e10cSrcweir // cause of flicker
106cdf0e10cSrcweir allocateChildAt( xChild, awt::Rectangle( 0,0,0,0 ) );
107cdf0e10cSrcweir }
108cdf0e10cSrcweir }
109cdf0e10cSrcweir
110cdf0e10cSrcweir awt::Size SAL_CALL
getMinimumSize()111cdf0e10cSrcweir Table::getMinimumSize() throw( uno::RuntimeException )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir int nRowsLen = 0;
114cdf0e10cSrcweir
115cdf0e10cSrcweir // 1. layout the table -- adjust to cope with row-spans...
116cdf0e10cSrcweir {
117cdf0e10cSrcweir // temporary 1D representation of the table
118cdf0e10cSrcweir std::vector< ChildData *> aTable;
119cdf0e10cSrcweir
120cdf0e10cSrcweir int col = 0;
121cdf0e10cSrcweir int row = 0;
122cdf0e10cSrcweir for ( std::list<Box_Base::ChildData *>::iterator it
123cdf0e10cSrcweir = maChildren.begin(); it != maChildren.end(); it++ )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir ChildData *child = static_cast<Table::ChildData*> ( *it );
126cdf0e10cSrcweir if ( !child->isVisible() )
127cdf0e10cSrcweir continue;
128cdf0e10cSrcweir
129cdf0e10cSrcweir while ( col + SAL_MIN( child->mnColSpan, mnColsLen ) > mnColsLen )
130cdf0e10cSrcweir {
131cdf0e10cSrcweir col = 0;
132cdf0e10cSrcweir row++;
133cdf0e10cSrcweir
134cdf0e10cSrcweir unsigned int i = col +( row*mnColsLen );
135cdf0e10cSrcweir while ( aTable.size() > i && !aTable[ i ] )
136cdf0e10cSrcweir i++;
137cdf0e10cSrcweir
138cdf0e10cSrcweir col = i % mnColsLen;
139cdf0e10cSrcweir row = i / mnColsLen;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir
142cdf0e10cSrcweir child->mnLeftCol = col;
143cdf0e10cSrcweir child->mnRightCol = SAL_MIN( col + child->mnColSpan, mnColsLen );
144cdf0e10cSrcweir child->mnTopRow = row;
145cdf0e10cSrcweir child->mnBottomRow = row + child->mnRowSpan;
146cdf0e10cSrcweir
147cdf0e10cSrcweir col += child->mnColSpan;
148cdf0e10cSrcweir
149cdf0e10cSrcweir unsigned int start = child->mnLeftCol +( child->mnTopRow*mnColsLen );
150cdf0e10cSrcweir unsigned int end =( child->mnRightCol-1 ) +( ( child->mnBottomRow-1 )*mnColsLen );
151cdf0e10cSrcweir if ( aTable.size() < end+1 )
152cdf0e10cSrcweir aTable.resize( end+1, NULL );
153cdf0e10cSrcweir for ( unsigned int i = start; i < end; i++ )
154cdf0e10cSrcweir aTable[ i ] = child;
155cdf0e10cSrcweir
156cdf0e10cSrcweir nRowsLen = SAL_MAX( nRowsLen, child->mnBottomRow );
157cdf0e10cSrcweir }
158cdf0e10cSrcweir }
159cdf0e10cSrcweir
160cdf0e10cSrcweir // 2. calculate columns/rows sizes
161cdf0e10cSrcweir for ( int g = 0; g < 2; g++ )
162cdf0e10cSrcweir {
163cdf0e10cSrcweir std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
164cdf0e10cSrcweir
165cdf0e10cSrcweir aGroup.clear();
166cdf0e10cSrcweir aGroup.resize( g == 0 ? mnColsLen : nRowsLen );
167cdf0e10cSrcweir
168cdf0e10cSrcweir // 2.1 base sizes on one-column/row children
169cdf0e10cSrcweir for ( std::list<Box_Base::ChildData *>::iterator it
170cdf0e10cSrcweir = maChildren.begin(); it != maChildren.end(); it++ )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir ChildData *child = static_cast<Table::ChildData*> ( *it );
173cdf0e10cSrcweir if ( !child->isVisible() )
174cdf0e10cSrcweir continue;
175cdf0e10cSrcweir const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
176cdf0e10cSrcweir const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
177cdf0e10cSrcweir
178cdf0e10cSrcweir if ( nFirstAttach == nLastAttach-1 )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir child->maRequisition = child->mxChild->getMinimumSize();
181cdf0e10cSrcweir int attach = nFirstAttach;
182cdf0e10cSrcweir int child_size = g == 0 ? child->maRequisition.Width
183cdf0e10cSrcweir : child->maRequisition.Height;
184cdf0e10cSrcweir aGroup[ attach ].mnSize = SAL_MAX( aGroup[ attach ].mnSize,
185cdf0e10cSrcweir child_size );
186cdf0e10cSrcweir if ( child->mbExpand[ g ] )
187cdf0e10cSrcweir aGroup[ attach ].mbExpand = true;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir }
190cdf0e10cSrcweir
191cdf0e10cSrcweir // 2.2 make sure multiple-columns/rows children fit
192cdf0e10cSrcweir for ( std::list<Box_Base::ChildData *>::iterator it
193cdf0e10cSrcweir = maChildren.begin(); it != maChildren.end(); it++ )
194cdf0e10cSrcweir {
195cdf0e10cSrcweir ChildData *child = static_cast<Table::ChildData*> ( *it );
196cdf0e10cSrcweir if ( !child->isVisible() )
197cdf0e10cSrcweir continue;
198cdf0e10cSrcweir const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
199cdf0e10cSrcweir const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
200cdf0e10cSrcweir
201cdf0e10cSrcweir if ( nFirstAttach != nLastAttach-1 )
202cdf0e10cSrcweir {
203cdf0e10cSrcweir child->maRequisition = child->mxChild->getMinimumSize();
204cdf0e10cSrcweir int size = 0;
205cdf0e10cSrcweir int expandables = 0;
206cdf0e10cSrcweir for ( int i = nFirstAttach; i < nLastAttach; i++ )
207cdf0e10cSrcweir {
208cdf0e10cSrcweir size += aGroup[ i ].mnSize;
209cdf0e10cSrcweir if ( aGroup[ i ].mbExpand )
210cdf0e10cSrcweir expandables++;
211cdf0e10cSrcweir }
212cdf0e10cSrcweir
213cdf0e10cSrcweir int child_size = g == 0 ? child->maRequisition.Width
214cdf0e10cSrcweir : child->maRequisition.Height;
215cdf0e10cSrcweir int extra = child_size - size;
216cdf0e10cSrcweir if ( extra > 0 )
217cdf0e10cSrcweir {
218cdf0e10cSrcweir if ( expandables )
219cdf0e10cSrcweir extra /= expandables;
220cdf0e10cSrcweir else
221cdf0e10cSrcweir extra /= nLastAttach - nFirstAttach;
222cdf0e10cSrcweir
223cdf0e10cSrcweir for ( int i = nFirstAttach; i < nLastAttach; i++ )
224cdf0e10cSrcweir if ( expandables == 0 || aGroup[ i ].mbExpand )
225cdf0e10cSrcweir aGroup[ i ].mnSize += extra;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir }
228cdf0e10cSrcweir }
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
231cdf0e10cSrcweir // 3. Sum everything up
232cdf0e10cSrcweir mnColExpandables =( mnRowExpandables = 0 );
233cdf0e10cSrcweir maRequisition.Width =( maRequisition.Height = 0 );
234cdf0e10cSrcweir for ( std::vector<GroupData>::iterator it = maCols.begin();
235cdf0e10cSrcweir it != maCols.end(); it++ )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir maRequisition.Width += it->mnSize;
238cdf0e10cSrcweir if ( it->mbExpand )
239cdf0e10cSrcweir mnColExpandables++;
240cdf0e10cSrcweir }
241cdf0e10cSrcweir for ( std::vector<GroupData>::iterator it = maRows.begin();
242cdf0e10cSrcweir it != maRows.end(); it++ )
243cdf0e10cSrcweir {
244cdf0e10cSrcweir maRequisition.Height += it->mnSize;
245cdf0e10cSrcweir if ( it->mbExpand )
246cdf0e10cSrcweir mnRowExpandables++;
247cdf0e10cSrcweir }
248cdf0e10cSrcweir
249cdf0e10cSrcweir return maRequisition;
250cdf0e10cSrcweir }
251cdf0e10cSrcweir
252cdf0e10cSrcweir void SAL_CALL
allocateArea(const awt::Rectangle & rArea)253cdf0e10cSrcweir Table::allocateArea( const awt::Rectangle &rArea )
254cdf0e10cSrcweir throw( uno::RuntimeException )
255cdf0e10cSrcweir {
256cdf0e10cSrcweir maAllocation = rArea;
257cdf0e10cSrcweir if ( maCols.size() == 0 || maRows.size() == 0 )
258cdf0e10cSrcweir return;
259cdf0e10cSrcweir
260cdf0e10cSrcweir int nExtraSize[ 2 ] = { SAL_MAX( rArea.Width - maRequisition.Width, 0 ),
261cdf0e10cSrcweir SAL_MAX( rArea.Height - maRequisition.Height, 0 ) };
262cdf0e10cSrcweir // split it
263cdf0e10cSrcweir nExtraSize[ 0 ] /= mnColExpandables ? mnColExpandables : mnColsLen;
264cdf0e10cSrcweir nExtraSize[ 1 ] /= mnRowExpandables ? mnRowExpandables : maRows.size();
265cdf0e10cSrcweir
266cdf0e10cSrcweir for ( std::list<Box_Base::ChildData *>::const_iterator it
267cdf0e10cSrcweir = maChildren.begin(); it != maChildren.end(); it++ )
268cdf0e10cSrcweir {
269cdf0e10cSrcweir ChildData *child = static_cast<Table::ChildData*> ( *it );
270cdf0e10cSrcweir if ( !child->isVisible() )
271cdf0e10cSrcweir continue;
272cdf0e10cSrcweir
273cdf0e10cSrcweir awt::Rectangle rChildArea( rArea.X, rArea.Y, 0, 0 );
274cdf0e10cSrcweir
275cdf0e10cSrcweir for ( int g = 0; g < 2; g++ )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
278cdf0e10cSrcweir const int nFirstAttach = g == 0 ? child->mnLeftCol : child->mnTopRow;
279cdf0e10cSrcweir const int nLastAttach = g == 0 ? child->mnRightCol : child->mnBottomRow;
280cdf0e10cSrcweir
281cdf0e10cSrcweir for ( int i = 0; i < nFirstAttach; i++ )
282cdf0e10cSrcweir {
283cdf0e10cSrcweir int gSize = aGroup[ i ].mnSize;
284cdf0e10cSrcweir if ( aGroup[ i ].mbExpand )
285cdf0e10cSrcweir gSize += nExtraSize[ g ];
286cdf0e10cSrcweir if ( g == 0 )
287cdf0e10cSrcweir rChildArea.X += gSize;
288cdf0e10cSrcweir else
289cdf0e10cSrcweir rChildArea.Y += gSize;
290cdf0e10cSrcweir }
291cdf0e10cSrcweir for ( int i = nFirstAttach; i < nLastAttach; i++ )
292cdf0e10cSrcweir {
293cdf0e10cSrcweir int gSize = aGroup[ i ].mnSize;
294cdf0e10cSrcweir if ( aGroup[ i ].mbExpand )
295cdf0e10cSrcweir gSize += nExtraSize[ g ];
296cdf0e10cSrcweir if ( g == 0 )
297cdf0e10cSrcweir rChildArea.Width += gSize;
298cdf0e10cSrcweir else
299cdf0e10cSrcweir rChildArea.Height += gSize;
300cdf0e10cSrcweir }
301cdf0e10cSrcweir }
302cdf0e10cSrcweir
303cdf0e10cSrcweir allocateChildAt( child->mxChild, rChildArea );
304cdf0e10cSrcweir }
305cdf0e10cSrcweir }
306cdf0e10cSrcweir
307cdf0e10cSrcweir } // namespace layoutimpl
308