]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/sizer.cpp
Unicode overview added
[wxWidgets.git] / src / common / sizer.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
3// Purpose: provide new wxSizer class for layout
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#include "wx/statbox.h"
26
27//---------------------------------------------------------------------------
28
29IMPLEMENT_ABSTRACT_CLASS(wxSizerItem, wxObject);
30IMPLEMENT_ABSTRACT_CLASS(wxSizer, wxObject);
31IMPLEMENT_ABSTRACT_CLASS(wxBoxSizer, wxSizer);
32IMPLEMENT_ABSTRACT_CLASS(wxStaticBoxSizer, wxBoxSizer);
33
34//---------------------------------------------------------------------------
35// wxSizerItem
36//---------------------------------------------------------------------------
37
38wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int border, wxObject* userData )
39{
40 m_window = (wxWindow *) NULL;
41 m_sizer = (wxSizer *) NULL;
42 m_option = option;
43 m_border = border;
44 m_flag = flag;
45 m_userData = userData;
46
47 // minimal size is the initial size
48 m_minSize.x = width;
49 m_minSize.y = height;
50
51 // size is set directly
52 m_size = m_minSize;
53}
54
55wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border, wxObject* userData )
56{
57 m_window = window;
58 m_sizer = (wxSizer *) NULL;
59 m_option = option;
60 m_border = border;
61 m_flag = flag;
62 m_userData = userData;
63
64 // minimal size is the initial size
65 m_minSize = window->GetSize();
66
67 // size is calculated later
68 // m_size = ...
69}
70
71wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
72{
73 m_window = (wxWindow *) NULL;
74 m_sizer = sizer;
75 m_option = option;
76 m_border = border;
77 m_flag = flag;
78 m_userData = userData;
79
80 // minimal size is calculated later
81 // m_minSize = ...
82
83 // size is calculated later
84 // m_size = ...
85}
86
87wxSizerItem::~wxSizerItem()
88{
89 if (m_userData)
90 delete m_userData;
91 if (m_sizer)
92 delete m_sizer;
93}
94
95
96wxSize wxSizerItem::GetSize()
97{
98 wxSize ret;
99 if (IsSizer())
100 ret = m_sizer->GetSize();
101 else
102 if (IsWindow())
103 ret = m_window->GetSize();
104 else ret = m_size;
105
106 if (m_flag & wxWEST)
107 ret.x += m_border;
108 if (m_flag & wxEAST)
109 ret.x += m_border;
110 if (m_flag & wxNORTH)
111 ret.y += m_border;
112 if (m_flag & wxSOUTH)
113 ret.y += m_border;
114
115 return ret;
116}
117
118wxSize wxSizerItem::CalcMin()
119{
120 wxSize ret;
121 if (IsSizer())
122 ret = m_sizer->CalcMin();
123/*
124 The minimum size of a window should be the
125 initial size, as saved in m_minSize, not the
126 current size.
127
128 else
129 if (IsWindow())
130 ret = m_window->GetSize();
131*/
132 else ret = m_minSize;
133
134 if (m_flag & wxWEST)
135 ret.x += m_border;
136 if (m_flag & wxEAST)
137 ret.x += m_border;
138 if (m_flag & wxNORTH)
139 ret.y += m_border;
140 if (m_flag & wxSOUTH)
141 ret.y += m_border;
142
143 return ret;
144}
145
146void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
147{
148 if (m_flag & wxWEST)
149 {
150 pos.x += m_border;
151 size.x -= m_border;
152 }
153 if (m_flag & wxEAST)
154 {
155 size.x -= m_border;
156 }
157 if (m_flag & wxNORTH)
158 {
159 pos.y += m_border;
160 size.y -= m_border;
161 }
162 if (m_flag & wxSOUTH)
163 {
164 size.y -= m_border;
165 }
166
167 if (IsSizer())
168 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
169
170 if (IsWindow())
171 m_window->SetSize( pos.x, pos.y, size.x, size.y );
172
173 m_size = size;
174}
175
176bool wxSizerItem::IsWindow()
177{
178 return (m_window != NULL);
179}
180
181bool wxSizerItem::IsSizer()
182{
183 return (m_sizer != NULL);
184}
185
186bool wxSizerItem::IsSpacer()
187{
188 return (m_window == NULL) && (m_sizer == NULL);
189}
190
191//---------------------------------------------------------------------------
192// wxSizer
193//---------------------------------------------------------------------------
194
195wxSizer::wxSizer()
196{
197 m_children.DeleteContents( TRUE );
198}
199
200wxSizer::~wxSizer()
201{
202}
203
204void wxSizer::Add( wxWindow *window, int option, int flag, int border, wxObject* userData )
205{
206 m_children.Append( new wxSizerItem( window, option, flag, border, userData ) );
207}
208
209void wxSizer::Add( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
210{
211 m_children.Append( new wxSizerItem( sizer, option, flag, border, userData ) );
212}
213
214void wxSizer::Add( int width, int height, int option, int flag, int border, wxObject* userData )
215{
216 m_children.Append( new wxSizerItem( width, height, option, flag, border, userData ) );
217}
218
219void wxSizer::Prepend( wxWindow *window, int option, int flag, int border, wxObject* userData )
220{
221 m_children.Insert( new wxSizerItem( window, option, flag, border, userData ) );
222}
223
224void wxSizer::Prepend( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
225{
226 m_children.Insert( new wxSizerItem( sizer, option, flag, border, userData ) );
227}
228
229void wxSizer::Prepend( int width, int height, int option, int flag, int border, wxObject* userData )
230{
231 m_children.Insert( new wxSizerItem( width, height, option, flag, border, userData ) );
232}
233
234bool wxSizer::Remove( wxWindow *window )
235{
236 wxASSERT( window );
237
238 wxNode *node = m_children.First();
239 while (node)
240 {
241 wxSizerItem *item = (wxSizerItem*)node->Data();
242 if (item->GetWindow() == window)
243 {
244 m_children.DeleteNode( node );
245 return TRUE;
246 }
247 node = node->Next();
248 }
249
250 return FALSE;
251}
252
253bool wxSizer::Remove( wxSizer *sizer )
254{
255 wxASSERT( sizer );
256
257 wxNode *node = m_children.First();
258 while (node)
259 {
260 wxSizerItem *item = (wxSizerItem*)node->Data();
261 if (item->GetSizer() == sizer)
262 {
263 m_children.DeleteNode( node );
264 return TRUE;
265 }
266 node = node->Next();
267 }
268
269 return FALSE;
270}
271
272bool wxSizer::Remove( int pos )
273{
274 wxNode *node = m_children.Nth( pos );
275 if (!node) return FALSE;
276
277 m_children.DeleteNode( node );
278
279 return TRUE;
280}
281
282void wxSizer::Fit( wxWindow *window )
283{
284 window->SetSize( GetMinWindowSize( window ) );
285}
286
287void wxSizer::Layout()
288{
289 CalcMin();
290 RecalcSizes();
291}
292
293void wxSizer::SetSizeHints( wxWindow *window )
294{
295 wxSize size( GetMinWindowSize( window ) );
296 window->SetSizeHints( size.x, size.y );
297}
298
299wxSize wxSizer::GetMinWindowSize( wxWindow *window )
300{
301 wxSize minSize( GetMinSize() );
302 wxSize size( window->GetSize() );
303 wxSize client_size( window->GetClientSize() );
304 return wxSize( minSize.x+size.x-client_size.x,
305 minSize.y+size.y-client_size.y );
306}
307
308void wxSizer::SetDimension( int x, int y, int width, int height )
309{
310 m_position.x = x;
311 m_position.y = y;
312 m_size.x = width;
313 m_size.y = height;
314 CalcMin();
315 RecalcSizes();
316}
317
318//---------------------------------------------------------------------------
319// wxBoxSizer
320//---------------------------------------------------------------------------
321
322wxBoxSizer::wxBoxSizer( int orient )
323{
324 m_orient = orient;
325}
326
327void wxBoxSizer::RecalcSizes()
328{
329 if (m_children.GetCount() == 0)
330 return;
331
332 int delta = 0;
333 int extra = 0;
334 if (m_stretchable)
335 {
336 if (m_orient == wxHORIZONTAL)
337 {
338 delta = (m_size.x - m_fixedWidth) / m_stretchable;
339 extra = (m_size.x - m_fixedWidth) % m_stretchable;
340 }
341 else
342 {
343 delta = (m_size.y - m_fixedHeight) / m_stretchable;
344 extra = (m_size.y - m_fixedHeight) % m_stretchable;
345 }
346 }
347
348 wxPoint pt( m_position );
349
350 wxNode *node = m_children.GetFirst();
351 while (node)
352 {
353 wxSizerItem *item = (wxSizerItem*) node->Data();
354
355 int weight = 1;
356 if (item->GetOption())
357 weight = item->GetOption();
358
359 wxSize size( item->CalcMin() );
360
361 if (m_orient == wxVERTICAL)
362 {
363 long height = size.y;
364 if (item->GetOption())
365 {
366 height = (delta * weight) + extra;
367 extra = 0; // only the first item will get the remainder as extra size
368 }
369
370 wxPoint child_pos( pt );
371 wxSize child_size( wxSize( size.x, height) );
372
373 if (item->GetFlag() & wxALIGN_RIGHT)
374 child_pos.x += m_size.x - size.x;
375 else if (item->GetFlag() & wxCENTER)
376 child_pos.x += (m_size.x - size.x) / 2;
377 else if (item->GetFlag() & wxEXPAND)
378 child_size.x = m_size.x;
379
380 item->SetDimension( child_pos, child_size );
381
382 pt.y += height;
383 }
384 else
385 {
386 long width = size.x;
387 if (item->GetOption())
388 {
389 width = (delta * weight) + extra;
390 extra = 0; // only the first item will get the remainder as extra size
391 }
392
393 wxPoint child_pos( pt );
394 wxSize child_size( wxSize(width, size.y) );
395
396 if (item->GetFlag() & wxALIGN_BOTTOM)
397 child_pos.y += m_size.y - size.y;
398 else if (item->GetFlag() & wxCENTER)
399 child_pos.y += (m_size.y - size.y) / 2;
400 else if (item->GetFlag() & wxEXPAND)
401 child_size.y = m_size.y;
402
403 item->SetDimension( child_pos, child_size );
404
405 pt.x += width;
406 }
407
408 node = node->Next();
409 }
410}
411
412wxSize wxBoxSizer::CalcMin()
413{
414 if (m_children.GetCount() == 0)
415 return wxSize(2,2);
416
417 m_stretchable = 0;
418 m_minWidth = 0;
419 m_minHeight = 0;
420 m_fixedWidth = 0;
421 m_fixedHeight = 0;
422
423 wxNode *node = m_children.GetFirst();
424 while (node)
425 {
426 wxSizerItem *item = (wxSizerItem*) node->Data();
427
428 int weight = 1;
429 if (item->GetOption())
430 weight = item->GetOption();
431
432 wxSize size( item->CalcMin() );
433
434 if (m_orient == wxHORIZONTAL)
435 {
436 m_minWidth += (size.x * weight);
437 m_minHeight = wxMax( m_minHeight, size.y );
438 }
439 else
440 {
441 m_minHeight += (size.y * weight);
442 m_minWidth = wxMax( m_minWidth, size.x );
443 }
444
445 if (item->GetOption())
446 {
447 m_stretchable += weight;
448 }
449 else
450 {
451 if (m_orient == wxVERTICAL)
452 {
453 m_fixedHeight += size.y;
454 m_fixedWidth = wxMax( m_fixedWidth, size.x );
455 }
456 else
457 {
458 m_fixedWidth += size.x;
459 m_fixedHeight = wxMax( m_fixedHeight, size.y );
460 }
461 }
462
463 node = node->Next();
464 }
465
466 return wxSize( m_minWidth, m_minHeight );
467}
468
469//---------------------------------------------------------------------------
470// wxStaticBoxSizer
471//---------------------------------------------------------------------------
472
473wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
474 : wxBoxSizer( orient )
475{
476 wxASSERT_MSG( box, T("wxStaticBoxSizer needs a static box") );
477
478 m_staticBox = box;
479}
480
481void wxStaticBoxSizer::RecalcSizes()
482{
483 // this will have to be done platform by platform
484 // as there is no way to guess the thickness of
485 // a wxStaticBox border
486 int top_border = 15;
487 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
488 int other_border = 5;
489
490 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
491
492 wxPoint old_pos( m_position );
493 m_position.x += other_border;
494 m_position.y += top_border;
495 wxSize old_size( m_size );
496 m_size.x -= 2*other_border;
497 m_size.y -= top_border + other_border;
498
499 wxBoxSizer::RecalcSizes();
500
501 m_position = old_pos;
502 m_size = old_size;
503}
504
505wxSize wxStaticBoxSizer::CalcMin()
506{
507 // this will have to be done platform by platform
508 // as there is no way to guess the thickness of
509 // a wxStaticBox border
510 int top_border = 15;
511 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
512 int other_border = 5;
513
514 wxSize ret( wxBoxSizer::CalcMin() );
515 ret.x += 2*top_border;
516 ret.y += other_border + top_border;
517
518 return ret;
519}