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