1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
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 ************************************************************************/
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
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 );
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
) ),
80 Table::ChildData::ChildData( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
81 : Box_Base::ChildData( xChild
)
82 // , mbExpand( { 1, 1 } )
95 Table::createChild( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
97 return new ChildData( xChild
);
101 Table::createChildProps( Box_Base::ChildData
*pData
)
103 return new ChildProps( static_cast<Table::ChildData
*> ( pData
) );
107 Table::addChild( const uno::Reference
< awt::XLayoutConstrains
>& xChild
)
108 throw( uno::RuntimeException
, awt::MaxChildrenException
)
112 Box_Base::addChild( xChild
);
114 allocateChildAt( xChild
, awt::Rectangle( 0,0,0,0 ) );
119 Table::getMinimumSize() throw( uno::RuntimeException
)
123 // 1. layout the table -- adjust to cope with row-spans...
125 // temporary 1D representation of the table
126 std::vector
< ChildData
*> aTable
;
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() )
137 while ( col
+ SAL_MIN( child
->mnColSpan
, mnColsLen
) > mnColsLen
)
142 unsigned int i
= col
+( row
*mnColsLen
);
143 while ( aTable
.size() > i
&& !aTable
[ i
] )
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
++ )
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
;
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() )
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
,
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() )
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();
214 for ( int i
= nFirstAttach
; i
< nLastAttach
; i
++ )
216 size
+= aGroup
[ i
].mnSize
;
217 if ( aGroup
[ i
].mbExpand
)
221 int child_size
= g
== 0 ? child
->maRequisition
.Width
222 : child
->maRequisition
.Height
;
223 int extra
= child_size
- size
;
227 extra
/= expandables
;
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
;
249 for ( std::vector
<GroupData
>::iterator it
= maRows
.begin();
250 it
!= maRows
.end(); it
++ )
252 maRequisition
.Height
+= it
->mnSize
;
257 return maRequisition
;
261 Table::allocateArea( const awt::Rectangle
&rArea
)
262 throw( uno::RuntimeException
)
264 maAllocation
= rArea
;
265 if ( maCols
.size() == 0 || maRows
.size() == 0 )
268 int nExtraSize
[ 2 ] = { SAL_MAX( rArea
.Width
- maRequisition
.Width
, 0 ),
269 SAL_MAX( rArea
.Height
- maRequisition
.Height
, 0 ) };
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() )
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
];
295 rChildArea
.X
+= gSize
;
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
];
305 rChildArea
.Width
+= gSize
;
307 rChildArea
.Height
+= gSize
;
311 allocateChildAt( child
->mxChild
, rChildArea
);
315 } // namespace layoutimpl