gui: moar refactoring work.
[fail.git] / gui / game / VGroup.cpp
blob819426bc6f435ed02d93f48503d07a9c847e8948
1 #include "VGroup.h"
2 #include "Theme.h"
3 #include <vector>
5 using namespace awful;
6 using namespace awful::gui::game;
8 VGroup::VGroup( Container* pParent_ ) :
9 SimpleContainer( pParent_ ),
10 m_Spacing( 2.f )
14 void VGroup::calcMinMax()
16 SimpleContainer::calcMinMax();
18 bool bUnlimited = false;
19 math::Vector2f min, max;
20 float spacing = 0.f;
22 WidgetList::const_iterator it;
23 for( it = m_Children.begin(); it != m_Children.end(); ++it )
25 spacing += m_Spacing;
26 const math::Vector2f& cmin = ( *it )->getMinSize();
27 const math::Vector2f& cmax = ( *it )->getMaxSize();
29 min.y() += cmin.y();
30 max.y() += cmax.y();
31 if( !cmax.y() )
32 bUnlimited = true;
34 if( cmin.x() > min.x() )
35 min.x() = cmin.x();
37 if( cmax.x() > max.x() )
38 max.x() = cmax.x();
41 spacing -= m_Spacing;
42 min.y() += spacing;
43 max.y() += spacing;
45 if( max.x() && max.x() < min.x() )
46 max.x() = min.x();
48 if( bUnlimited )
49 max.y() = 0.f;
51 setMinSize( min );
52 setMaxSize( max );
55 enum WidgetLayoutState
57 s_Free,
58 s_Min,
59 s_Max
62 void VGroup::layout()
64 WidgetList::size_type numchildren = m_Children.size();
66 const math::Rectf& r( getRect() );
67 float FreeSpace = r.height() - m_Spacing * static_cast< float >( numchildren - 1 );
69 // Currently, all children have a weight of 1. I'll implement weighted layout
70 // if I need it (aka if I feel like it).
71 float TotalWeight = static_cast< float >( numchildren );
73 std::vector< WidgetLayoutState > states( numchildren );
74 bool bMoreSpace = true;
75 WidgetList::const_iterator it;
76 int i;
78 // Outer loop: loop until the inner loop manage to go through all the children
79 // without changing their layout state.
82 for( it = m_Children.begin(), i = 0; it != m_Children.end(); ++it, ++i )
84 const math::Vector2f& min = ( *it )->getMinSize();
85 const math::Vector2f& max = ( *it )->getMaxSize();
87 if( states[i] == s_Free )
89 float size = FreeSpace / TotalWeight;
90 if( size < min.y() )
92 states[i] = s_Min;
93 TotalWeight -= 1.f;
94 FreeSpace -= min.y();
95 bMoreSpace = false;
96 break;
99 if( max.y() && size > max.y() )
101 states[i] = s_Max;
102 TotalWeight -= 1.f;
103 FreeSpace -= max.y();
104 bMoreSpace = true;
105 break;
108 else
110 if( bMoreSpace && states[i] == s_Min )
112 TotalWeight += 1.f;
113 FreeSpace += min.y();
114 float size = FreeSpace / TotalWeight;
115 if( size > min.y() )
117 states[i] = s_Free;
118 break;
120 else
122 TotalWeight -= 1.f;
123 FreeSpace -= min.y();
127 if( !bMoreSpace && states[i] == s_Max )
129 TotalWeight += 1.f;
130 FreeSpace += max.y();
131 float size = FreeSpace / TotalWeight;
132 if( size < max.y() )
134 states[i] = s_Free;
135 break;
137 else
139 TotalWeight -= 1.f;
140 FreeSpace -= max.y();
145 } while( it != m_Children.end() );
147 math::Rectf crect;
149 for( it = m_Children.begin(), i = 0; it != m_Children.end(); ++it, ++i )
151 const math::Vector2f& min = ( *it )->getMinSize();
152 const math::Vector2f& max = ( *it )->getMaxSize();
154 crect.width() = r.width();
155 if( crect.width() < min.x() )
156 crect.width() = min.x();
157 if( max.x() && crect.width() > max.x() )
158 crect.height() = max.x();
160 switch( states[i] )
162 case s_Free:
163 crect.height() = FreeSpace / TotalWeight;
164 break;
166 case s_Min:
167 crect.height() = min.y();
168 break;
170 case s_Max:
171 crect.height() = max.y();
172 break;
175 ( *it )->setRect( crect );
176 crect.top() += crect.height() + m_Spacing;
179 SimpleContainer::layout();