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 <tools/debug.hxx>
35 #include <sal/macros.h>
37 // fixed point precision for distributing error
45 Box::ChildProps::ChildProps( Box::ChildData
*pData
)
47 addProp( RTL_CONSTASCII_USTRINGPARAM( "Expand" ),
48 ::getCppuType( static_cast< const sal_Bool
* >( NULL
) ),
50 addProp( RTL_CONSTASCII_USTRINGPARAM( "Fill" ),
51 ::getCppuType( static_cast< const sal_Bool
* >( NULL
) ),
53 addProp( RTL_CONSTASCII_USTRINGPARAM( "Padding" ),
54 ::getCppuType( static_cast< const sal_Int32
* >( NULL
) ),
55 &(pData
->mnPadding
) );
58 Box::ChildData::ChildData( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
59 : Box_Base::ChildData( xChild
)
67 Box::createChild( uno::Reference
< awt::XLayoutConstrains
> const& xChild
)
69 return new ChildData( xChild
);
73 Box::createChildProps( Box_Base::ChildData
*pData
)
75 return new ChildProps( static_cast<Box::ChildData
*> ( pData
) );
78 Box::Box( bool horizontal
)
81 , mbHomogeneous( false )
82 , mbHorizontal( horizontal
)
84 addProp( RTL_CONSTASCII_USTRINGPARAM( "Homogeneous" ),
85 ::getCppuType( static_cast< const sal_Bool
* >( NULL
) ),
87 addProp( RTL_CONSTASCII_USTRINGPARAM( "Spacing" ),
88 ::getCppuType( static_cast< const sal_Int32
* >( NULL
) ),
90 mbHasFlowChildren
= false;
94 Box::calculateSize( long nWidth
)
96 int nVisibleChildren
= 0;
97 // primary vs secundary axis (instead of a X and Y)
100 int nFlowMinWidth
= 0; // in case the box only has flow children
102 mbHasFlowChildren
= false;
104 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
105 = maChildren
.begin(); it
!= maChildren
.end(); it
++ )
107 ChildData
*child
= static_cast<Box::ChildData
*> ( *it
);
108 if ( !child
->isVisible() )
111 uno::Reference
< awt::XLayoutContainer
> xChildCont( child
->mxChild
, uno::UNO_QUERY
);
112 bool bFlow
= xChildCont
.is() && xChildCont
->hasHeightForWidth();
114 awt::Size aChildSize
= child
->maRequisition
= child
->mxChild
->getMinimumSize();
116 if ( !mbHorizontal
/*vertical*/ && bFlow
)
118 if ( nFlowMinWidth
== 0 || nFlowMinWidth
> aChildSize
.Width
)
119 nFlowMinWidth
= aChildSize
.Width
;
120 mbHasFlowChildren
= true;
124 int size
= primDim( aChildSize
) + child
->mnPadding
* 2;
126 nPrimSize
= SAL_MAX( nPrimSize
, size
);
130 nSecSize
= SAL_MAX( nSecSize
, secDim( aChildSize
) );
135 if ( nVisibleChildren
)
138 nPrimSize
*= nVisibleChildren
;
139 nPrimSize
+= (nVisibleChildren
- 1) * mnSpacing
;
142 if ( mbHasFlowChildren
)
145 nWidth
= nSecSize
? nSecSize
: nFlowMinWidth
;
146 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
147 = maChildren
.begin(); it
!= maChildren
.end(); it
++ )
149 ChildData
*child
= static_cast<Box::ChildData
*> ( *it
);
150 if ( !child
->isVisible() )
153 uno::Reference
< awt::XLayoutContainer
> xChildCont( child
->mxChild
, uno::UNO_QUERY
);
154 bool bFlow
= xChildCont
.is() && xChildCont
->hasHeightForWidth();
157 nPrimSize
+= xChildCont
->getHeightForWidth( nWidth
);
161 nPrimSize
+= mnBorderWidth
* 2;
162 nSecSize
+= mnBorderWidth
* 2;
163 return awt::Size( mbHorizontal
? nPrimSize
: nSecSize
,
164 mbHorizontal
? nSecSize
: nPrimSize
);
168 Box::getMinimumSize() throw(uno::RuntimeException
)
170 maRequisition
= calculateSize();
171 return maRequisition
;
175 Box::hasHeightForWidth()
176 throw(uno::RuntimeException
)
178 return mbHasFlowChildren
;
182 Box::getHeightForWidth( sal_Int32 nWidth
)
183 throw(uno::RuntimeException
)
185 if ( hasHeightForWidth() )
186 return calculateSize( nWidth
).Height
;
187 return maRequisition
.Height
;
191 Box::allocateArea( const awt::Rectangle
&newArea
)
192 throw (uno::RuntimeException
)
194 maAllocation
= newArea
;
195 int nVisibleChildren
= 0, nExpandChildren
= 0;
197 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
198 = maChildren
.begin(); it
!= maChildren
.end(); it
++ )
200 ChildData
*child
= static_cast<Box::ChildData
*> ( *it
);
201 if ( child
->isVisible() )
204 if ( child
->mbExpand
)
208 if ( !nVisibleChildren
)
211 // split rectangle for dimension helpers
212 awt::Point
newPoint( newArea
.X
, newArea
.Y
);
213 awt::Size
newSize( newArea
.Width
, newArea
.Height
);
217 nExtraSpace
= ( ( primDim( newSize
) - mnBorderWidth
* 2 -
218 ( nVisibleChildren
- 1 ) * mnSpacing
)) / nVisibleChildren
;
219 else if ( nExpandChildren
)
221 int reqSize
= primDim( maRequisition
);
222 if ( !mbHorizontal
&& hasHeightForWidth() )
223 reqSize
= getHeightForWidth( newArea
.Width
);
224 nExtraSpace
= ( primDim( newSize
) - reqSize
) / nExpandChildren
;
229 int nChildPrimPoint
, nChildSecPoint
, nChildPrimSize
, nChildSecSize
;
231 int nStartPoint
= primDim( newPoint
) + mnBorderWidth
;
232 int nBoxSecSize
= SAL_MAX( 1, secDim( newSize
) - mnBorderWidth
* 2 );
234 for ( std::list
<Box_Base::ChildData
*>::const_iterator it
235 = maChildren
.begin(); it
!= maChildren
.end(); it
++ )
237 ChildData
*child
= static_cast<Box::ChildData
*> ( *it
);
238 if ( !child
->isVisible() )
241 awt::Point aChildPos
;
242 int nBoxPrimSize
; // of the available box space
245 nBoxPrimSize
= nExtraSpace
;
248 uno::Reference
< awt::XLayoutContainer
> xChildCont( child
->mxChild
, uno::UNO_QUERY
);
249 bool bFlow
= xChildCont
.is() && xChildCont
->hasHeightForWidth();
250 if ( !mbHorizontal
&& bFlow
)
251 nBoxPrimSize
= xChildCont
->getHeightForWidth( newArea
.Width
);
253 nBoxPrimSize
= primDim( child
->maRequisition
);
254 nBoxPrimSize
+= child
->mnPadding
;
255 if ( child
->mbExpand
)
256 nBoxPrimSize
+= nExtraSpace
;
259 nChildPrimPoint
= nStartPoint
+ child
->mnPadding
;
260 nChildSecPoint
= secDim( newPoint
) + mnBorderWidth
;
262 nChildSecSize
= nBoxSecSize
;
264 nChildPrimSize
= SAL_MAX( 1, nBoxPrimSize
- child
->mnPadding
);
267 nChildPrimSize
= primDim( child
->maRequisition
);
268 nChildPrimPoint
+= (nBoxPrimSize
- nChildPrimSize
) / 2;
270 nChildSecPoint
+= (nBoxSecSize
- nChildSecSize
) / 2;
274 area
.X
= mbHorizontal
? nChildPrimPoint
: nChildSecPoint
;
275 area
.Y
= mbHorizontal
? nChildSecPoint
: nChildPrimPoint
;
276 area
.Width
= mbHorizontal
? nChildPrimSize
: nChildSecSize
;
277 area
.Height
= mbHorizontal
? nChildSecSize
: nChildPrimSize
;
279 allocateChildAt( child
->mxChild
, area
);
281 nStartPoint
+= nBoxPrimSize
+ mnSpacing
+ child
->mnPadding
;
285 } // namespace layoutimpl