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