ea3019c03760abbf73ddab47d11ba8f0b556dea1
[wxWidgets.git] / src / common / sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sizer.cpp
3 // Purpose: provide wxNewSizer class for layounting
4 // Author: Robert Roebling and Robin Dunn
5 // Modified by:
6 // Created:
7 // RCS-ID: $Id$
8 // Copyright: (c) Robin Dunn, Dirk Holtwick and Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef __WXSIZERS_H__
13 #define __WXSIZERS_H__
14
15 #ifdef __GNUG__
16 #pragma implementation "sizer.h"
17 #endif
18
19 #include "wx/sizer.h"
20 #include "wx/utils.h"
21
22 //---------------------------------------------------------------------------
23 // wxNewSizerItem
24 //---------------------------------------------------------------------------
25
26 wxNewSizerItem::wxNewSizerItem( int width, int height, int option )
27 {
28 m_window = (wxWindow *) NULL;
29 m_sizer = (wxNewSizer *) NULL;
30 m_minSize.x = width;
31 m_minSize.y = height;
32 m_option = option;
33 }
34
35 wxNewSizerItem::wxNewSizerItem( wxWindow *window, int option )
36 {
37 m_window = window;
38 m_sizer = (wxNewSizer *) NULL;
39 m_minSize = window->GetSize();
40 m_option = option;
41 }
42
43 wxNewSizerItem::wxNewSizerItem( wxNewSizer *sizer, int option )
44 {
45 m_window = (wxWindow *) NULL;
46 m_sizer = sizer;
47 m_minSize = sizer->GetSize();
48 m_option = option;
49 }
50
51 wxSize wxNewSizerItem::GetSize()
52 {
53 if (IsNewSizer())
54 return m_sizer->GetSize();
55
56 if (IsWindow())
57 return m_window->GetSize();
58
59 return m_minSize;
60 }
61
62 wxSize wxNewSizerItem::CalcMin()
63 {
64 if (IsNewSizer())
65 return m_sizer->CalcMin();
66
67 if (IsWindow())
68 return m_window->GetSize();
69
70 return m_minSize;
71 }
72
73 void wxNewSizerItem::SetDimension( wxPoint pos, wxSize size )
74 {
75 if (IsNewSizer())
76 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
77
78 if (IsWindow())
79 m_window->SetSize( pos.x, pos.y, size.x, size.y );
80
81 m_minSize = size;
82 }
83
84 bool wxNewSizerItem::IsWindow()
85 {
86 return (m_window != NULL);
87 }
88
89 bool wxNewSizerItem::IsNewSizer()
90 {
91 return (m_sizer != NULL);
92 }
93
94 bool wxNewSizerItem::IsSpacer()
95 {
96 return (m_window == NULL) && (m_sizer == NULL);
97 }
98
99 //---------------------------------------------------------------------------
100 // wxNewSizer
101 //---------------------------------------------------------------------------
102
103 wxNewSizer::wxNewSizer()
104 {
105 m_children.DeleteContents( TRUE );
106 }
107
108 wxNewSizer::~wxNewSizer()
109 {
110 }
111
112 void wxNewSizer::Add( wxWindow *window, int option )
113 {
114 m_children.Append( new wxNewSizerItem( window, option ) );
115 }
116
117 void wxNewSizer::Add( wxNewSizer *sizer, int option )
118 {
119 m_children.Append( new wxNewSizerItem( sizer, option ) );
120 }
121
122 void wxNewSizer::Add( int width, int height, int option )
123 {
124 m_children.Append( new wxNewSizerItem( width, height, option ) );
125 }
126
127 void wxNewSizer::Fit( wxWindow *window )
128 {
129 window->SetSize( GetMinWindowSize( window ) );
130 }
131
132 void wxNewSizer::Layout()
133 {
134 m_size = CalcMin();
135 RecalcSizes();
136 }
137
138 void wxNewSizer::SetSizeHints( wxWindow *window )
139 {
140 wxSize size( GetMinWindowSize( window ) );
141 window->SetSizeHints( size.x, size.y );
142 }
143
144 wxSize wxNewSizer::GetMinWindowSize( wxWindow *window )
145 {
146 wxSize min( GetMinSize() );
147 wxSize size( window->GetSize() );
148 wxSize client_size( window->GetClientSize() );
149 return wxSize( min.x+size.x-client_size.x, min.y+size.y-client_size.y );
150 }
151
152 void wxNewSizer::SetDimension( int x, int y, int width, int height )
153 {
154 m_position.x = x;
155 m_position.y = y;
156 m_size.x = width;
157 m_size.y = height;
158 RecalcSizes();
159 }
160
161 //---------------------------------------------------------------------------
162 // wxBorderNewSizer
163 //---------------------------------------------------------------------------
164
165 wxBorderNewSizer::wxBorderNewSizer( int sides )
166 {
167 m_sides = sides;
168 }
169
170 void wxBorderNewSizer::Add( wxWindow *window, int option )
171 {
172 wxCHECK_RET( m_children.GetCount() == 0, _T("border sizer can only hold one child") );
173
174 wxNewSizer::Add( window, option );
175 }
176
177 void wxBorderNewSizer::Add( wxNewSizer *sizer, int option )
178 {
179 wxCHECK_RET( m_children.GetCount() == 0, _T("border sizer can only hold one child") );
180
181 wxNewSizer::Add( sizer, option );
182 }
183
184 void wxBorderNewSizer::Add( int width, int height, int option )
185 {
186 wxCHECK_RET( m_children.GetCount() == 0, _T("border sizer can only hold one child") );
187
188 wxNewSizer::Add( width, height, option );
189 }
190
191 void wxBorderNewSizer::RecalcSizes()
192 {
193 wxNode *node = m_children.GetFirst();
194
195 if (!node)
196 {
197 SetDimension( m_position.x, m_position.y, 2, 2 );
198 return;
199 }
200
201 wxNewSizerItem *item = (wxNewSizerItem*) node->Data();
202
203 wxSize size( m_size );
204 wxPoint pt( m_position );
205 int borderSize = item->GetOption();
206
207 if (m_sides & wxWEST)
208 {
209 size.x -= borderSize;
210 pt.x += borderSize;
211 }
212 if (m_sides & wxEAST)
213 {
214 size.x -= borderSize;
215 }
216 if (m_sides & wxNORTH)
217 {
218 size.y -= borderSize;
219 pt.y += borderSize;
220 }
221 if (m_sides & wxSOUTH)
222 {
223 size.y -= borderSize;
224 }
225
226 item->SetDimension( pt, size );
227 }
228
229 wxSize wxBorderNewSizer::CalcMin()
230 {
231 wxNode *node = m_children.GetFirst();
232
233 if (!node)
234 return wxSize(2,2);
235
236 wxNewSizerItem *item = (wxNewSizerItem*) node->Data();
237
238 wxSize size( item->CalcMin() );
239
240 int borderSize = item->GetOption();
241
242 if (m_sides & wxWEST)
243 size.x += borderSize;
244 if (m_sides & wxEAST)
245 size.x += borderSize;
246 if (m_sides & wxNORTH)
247 size.y += borderSize;
248 if (m_sides & wxSOUTH)
249 size.y += borderSize;
250
251 return size;
252 }
253
254 //---------------------------------------------------------------------------
255 // wxBoxNewSizer
256 //---------------------------------------------------------------------------
257
258 wxBoxNewSizer::wxBoxNewSizer( int orient )
259 {
260 m_orient = orient;
261 }
262
263 void wxBoxNewSizer::RecalcSizes()
264 {
265 if (m_children.GetCount() == 0)
266 {
267 SetDimension( m_position.x, m_position.y, 2, 2 );
268 return;
269 }
270
271 int delta = 0;
272 int extra = 0;
273 if (m_stretchable)
274 {
275 if (m_orient == wxHORIZONTAL)
276 {
277 delta = (m_size.x - m_fixedWidth) / m_stretchable;
278 extra = (m_size.x - m_fixedWidth) % m_stretchable;
279 }
280 else
281 {
282 delta = (m_size.y - m_fixedHeight) / m_stretchable;
283 extra = (m_size.y - m_fixedHeight) % m_stretchable;
284 }
285 }
286
287 wxPoint pt( m_position );
288
289 wxNode *node = m_children.GetFirst();
290 while (node)
291 {
292 wxNewSizerItem *item = (wxNewSizerItem*) node->Data();
293
294 int weight = 1;
295 if (item->GetOption())
296 weight = item->GetOption();
297
298 wxSize size( item->CalcMin() );
299
300 if (m_orient == wxVERTICAL)
301 {
302 long height = size.y;
303 if (item->GetOption())
304 {
305 height = (delta * weight) + extra;
306 extra = 0; // only the first item will get the remainder as extra size
307 }
308 item->SetDimension( pt, wxSize( size.x, height) );
309 pt.y += height;
310 }
311 else
312 {
313 long width = size.x;
314 if (item->GetOption())
315 {
316 width = (delta * weight) + extra;
317 extra = 0; // only the first item will get the remainder as extra size
318 }
319 item->SetDimension( pt, wxSize(width, size.y) );
320 pt.x += width;
321 }
322
323 node = node->Next();
324 }
325 }
326
327 wxSize wxBoxNewSizer::CalcMin()
328 {
329 if (m_children.GetCount() == 0)
330 return wxSize(2,2);
331
332 m_stretchable = 0;
333 m_minWidth = 0;
334 m_minHeight = 0;
335 m_fixedWidth = 0;
336 m_fixedHeight = 0;
337
338 wxNode *node = m_children.GetFirst();
339 while (node)
340 {
341 wxNewSizerItem *item = (wxNewSizerItem*) node->Data();
342
343 int weight = 1;
344 if (item->GetOption())
345 weight = item->GetOption();
346
347 wxSize size( item->CalcMin() );
348
349 if (m_orient == wxHORIZONTAL)
350 {
351 m_minWidth += (size.x * weight);
352 m_minHeight = wxMax( m_minHeight, size.y );
353 }
354 else
355 {
356 m_minHeight += (size.y * weight);
357 m_minWidth = wxMax( m_minWidth, size.x );
358 }
359
360 if (item->GetOption())
361 {
362 m_stretchable += weight;
363 }
364 else
365 {
366 if (m_orient == wxVERTICAL)
367 {
368 m_fixedHeight += size.y;
369 m_fixedWidth = wxMax( m_fixedWidth, size.x );
370 }
371 else
372 {
373 m_fixedWidth += size.x;
374 m_fixedHeight = wxMax( m_fixedHeight, size.y );
375 }
376 }
377
378 node = node->Next();
379 }
380
381 return wxSize( m_minWidth, m_minHeight );
382 }
383
384 #endif
385 // __SIZERS_H__