Added GPLv3 headers all over the place.
[fail.git] / src / gui / game / HGroup.cpp
blob5d5bc736e2d022d2f41bf69a5ef2c1f559bd6669
1 /*
2 Fail game engine
3 Copyright 2007 Antoine Chavasse <a.chavasse@gmail.com>
5 This file is part of Fail.
7 Fail is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 3
9 as published by the Free Software Foundation.
11 Fail is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "gui/game/HGroup.h"
20 #include "gui/game/Theme.h"
21 #include <vector>
23 using namespace fail;
24 using namespace fail::gui::game;
26 HGroup::HGroup( Container* pParent_ ) :
27 SimpleContainer( pParent_ ),
28 m_Spacing( 2.f )
32 void HGroup::reLayout()
34 calcMinMax();
36 const math::Vector2f& minsize = getMinSize();
37 const math::Vector2f& maxsize = getMaxSize();
38 math::Rectf rect( getRect() );
40 if( rect.width() < minsize.x() ||
41 rect.width() > maxsize.x() ||
42 rect.height() < minsize.y() ||
43 rect.height() > maxsize.y() )
44 m_pParent->reLayout();
45 else
46 layout();
49 void HGroup::calcMinMax()
51 SimpleContainer::calcMinMax();
53 bool bUnlimited = false;
54 math::Vector2f min, max;
55 float spacing = 0.f;
57 WidgetList::const_iterator it;
58 for( it = m_Children.begin(); it != m_Children.end(); ++it )
60 spacing += m_Spacing;
61 const math::Vector2f& cmin = ( *it )->getMinSize();
62 const math::Vector2f& cmax = ( *it )->getMaxSize();
64 min.x() += cmin.x();
65 max.x() += cmax.x();
66 if( !cmax.x() )
67 bUnlimited = true;
69 if( cmin.y() > min.y() )
70 min.y() = cmin.y();
72 if( cmax.y() > max.y() )
73 max.y() = cmax.y();
76 spacing -= m_Spacing;
77 min.x() += spacing;
78 max.x() += spacing;
80 if( max.y() && max.y() < min.y() )
81 max.y() = min.y();
83 if( bUnlimited )
84 max.x() = 0.f;
86 setMinSize( min );
87 setMaxSize( max );
90 enum WidgetLayoutState
92 s_Free,
93 s_Min,
94 s_Max
97 void HGroup::layout()
99 WidgetList::size_type numchildren = m_Children.size();
101 const math::Rectf& r( getRect() );
102 float FreeSpace = r.width() - m_Spacing * static_cast< float >( numchildren - 1 );
104 // Currently, all children have a weight of 1. I'll implement weighted layout
105 // if I need it (aka if I feel like it).
106 float TotalWeight = static_cast< float >( numchildren );
108 std::vector< WidgetLayoutState > states( numchildren );
109 bool bMoreSpace = true;
110 WidgetList::const_iterator it;
111 int i;
113 // Outer loop: loop until the inner loop manage to go through all the children
114 // without changing their layout state.
117 for( it = m_Children.begin(), i = 0; it != m_Children.end(); ++it, ++i )
119 const math::Vector2f& min = ( *it )->getMinSize();
120 const math::Vector2f& max = ( *it )->getMaxSize();
122 if( states[i] == s_Free )
124 float size = FreeSpace / TotalWeight;
125 if( size < min.x() )
127 states[i] = s_Min;
128 TotalWeight -= 1.f;
129 FreeSpace -= min.x();
130 bMoreSpace = false;
131 break;
134 if( max.x() && size > max.x() )
136 states[i] = s_Max;
137 TotalWeight -= 1.f;
138 FreeSpace -= max.x();
139 bMoreSpace = true;
140 break;
143 else
145 if( bMoreSpace && states[i] == s_Min )
147 TotalWeight += 1.f;
148 FreeSpace += min.x();
149 float size = FreeSpace / TotalWeight;
150 if( size > min.x() )
152 states[i] = s_Free;
153 break;
155 else
157 TotalWeight -= 1.f;
158 FreeSpace -= min.x();
162 if( !bMoreSpace && states[i] == s_Max )
164 TotalWeight += 1.f;
165 FreeSpace += max.x();
166 float size = FreeSpace / TotalWeight;
167 if( size < max.x() )
169 states[i] = s_Free;
170 break;
172 else
174 TotalWeight -= 1.f;
175 FreeSpace -= max.x();
180 } while( it != m_Children.end() );
182 math::Rectf crect;
184 for( it = m_Children.begin(), i = 0; it != m_Children.end(); ++it, ++i )
186 const math::Vector2f& min = ( *it )->getMinSize();
187 const math::Vector2f& max = ( *it )->getMaxSize();
189 crect.height() = r.height();
190 if( crect.height() < min.y() )
191 crect.height() = min.y();
192 if( max.y() && crect.height() > max.y() )
193 crect.height() = max.y();
195 switch( states[i] )
197 case s_Free:
198 crect.width() = FreeSpace / TotalWeight;
199 break;
201 case s_Min:
202 crect.width() = min.x();
203 break;
205 case s_Max:
206 crect.width() = max.x();
207 break;
210 ( *it )->setRect( crect );
211 crect.left() += crect.width() + m_Spacing;
214 SimpleContainer::layout();