merge the formfield patch from ooo-build
[ooovba.git] / toolkit / source / layout / core / box.cxx
blob6acc8c8122a3076add583deb2e51b48571583e03
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 "box.hxx"
34 #include <tools/debug.hxx>
35 #include <sal/macros.h>
37 // fixed point precision for distributing error
38 #define FIXED_PT 16
40 namespace layoutimpl
43 using namespace css;
45 Box::ChildProps::ChildProps( Box::ChildData *pData )
47 addProp( RTL_CONSTASCII_USTRINGPARAM( "Expand" ),
48 ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
49 &(pData->mbExpand) );
50 addProp( RTL_CONSTASCII_USTRINGPARAM( "Fill" ),
51 ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
52 &(pData->mbFill) );
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 )
60 , mnPadding( 0 )
61 , mbExpand( true )
62 , mbFill( true )
66 Box::ChildData*
67 Box::createChild( uno::Reference< awt::XLayoutConstrains > const& xChild )
69 return new ChildData( xChild );
72 Box::ChildProps*
73 Box::createChildProps( Box_Base::ChildData *pData )
75 return new ChildProps( static_cast<Box::ChildData*> ( pData ) );
78 Box::Box( bool horizontal )
79 : Box_Base()
80 , mnSpacing( 0 )
81 , mbHomogeneous( false )
82 , mbHorizontal( horizontal )
84 addProp( RTL_CONSTASCII_USTRINGPARAM( "Homogeneous" ),
85 ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
86 &mbHomogeneous );
87 addProp( RTL_CONSTASCII_USTRINGPARAM( "Spacing" ),
88 ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
89 &mnSpacing );
90 mbHasFlowChildren = false;
93 awt::Size
94 Box::calculateSize( long nWidth )
96 int nVisibleChildren = 0;
97 // primary vs secundary axis (instead of a X and Y)
98 int nPrimSize = 0;
99 int nSecSize = 0;
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() )
109 continue;
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;
122 else
124 int size = primDim( aChildSize ) + child->mnPadding * 2;
125 if ( mbHomogeneous )
126 nPrimSize = SAL_MAX( nPrimSize, size );
127 else
128 nPrimSize += size;
130 nSecSize = SAL_MAX( nSecSize, secDim( aChildSize ) );
132 nVisibleChildren++;
135 if ( nVisibleChildren )
137 if ( mbHomogeneous )
138 nPrimSize *= nVisibleChildren;
139 nPrimSize += (nVisibleChildren - 1) * mnSpacing;
142 if ( mbHasFlowChildren )
144 if ( nWidth == 0 )
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() )
151 continue;
153 uno::Reference< awt::XLayoutContainer > xChildCont( child->mxChild, uno::UNO_QUERY );
154 bool bFlow = xChildCont.is() && xChildCont->hasHeightForWidth();
156 if ( bFlow )
157 nPrimSize += xChildCont->getHeightForWidth( nWidth );
161 nPrimSize += mnBorderWidth * 2;
162 nSecSize += mnBorderWidth * 2;
163 return awt::Size( mbHorizontal ? nPrimSize : nSecSize,
164 mbHorizontal ? nSecSize : nPrimSize );
167 awt::Size SAL_CALL
168 Box::getMinimumSize() throw(uno::RuntimeException)
170 maRequisition = calculateSize();
171 return maRequisition;
174 sal_Bool SAL_CALL
175 Box::hasHeightForWidth()
176 throw(uno::RuntimeException)
178 return mbHasFlowChildren;
181 sal_Int32 SAL_CALL
182 Box::getHeightForWidth( sal_Int32 nWidth )
183 throw(uno::RuntimeException)
185 if ( hasHeightForWidth() )
186 return calculateSize( nWidth ).Height;
187 return maRequisition.Height;
190 void SAL_CALL
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() )
203 nVisibleChildren++;
204 if ( child->mbExpand )
205 nExpandChildren++;
208 if ( !nVisibleChildren )
209 return;
211 // split rectangle for dimension helpers
212 awt::Point newPoint( newArea.X, newArea.Y );
213 awt::Size newSize( newArea.Width, newArea.Height );
215 int nExtraSpace;
216 if ( mbHomogeneous )
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;
226 else
227 nExtraSpace = 0;
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() )
239 continue;
241 awt::Point aChildPos;
242 int nBoxPrimSize; // of the available box space
244 if ( mbHomogeneous )
245 nBoxPrimSize = nExtraSpace;
246 else
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 );
252 else
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;
263 if ( child->mbFill )
264 nChildPrimSize = SAL_MAX( 1, nBoxPrimSize - child->mnPadding);
265 else
267 nChildPrimSize = primDim( child->maRequisition );
268 nChildPrimPoint += (nBoxPrimSize - nChildPrimSize) / 2;
270 nChildSecPoint += (nBoxSecSize - nChildSecSize) / 2;
273 awt::Rectangle area;
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