]> git.saurik.com Git - wxWidgets.git/blame - src/common/sizer.cpp
attempt to fix crash in tree ctrl
[wxWidgets.git] / src / common / sizer.cpp
CommitLineData
5279a24d
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: sizer.cpp
1044a386 3// Purpose: provide new wxSizer class for layout
5279a24d
RR
4// Author: Robert Roebling and Robin Dunn
5// Modified by:
0c0d686f 6// Created:
5279a24d
RR
7// RCS-ID: $Id$
8// Copyright: (c) Robin Dunn, Dirk Holtwick and Robert Roebling
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
5279a24d 12#ifdef __GNUG__
c62ac5b6 13#pragma implementation "sizer.h"
5279a24d
RR
14#endif
15
77671fd2
VZ
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
5279a24d 23#include "wx/sizer.h"
61d514bb 24#include "wx/utils.h"
27ea1d8a 25#include "wx/statbox.h"
83edc0a5 26#include "wx/notebook.h"
5279a24d 27
0c0d686f
RD
28//---------------------------------------------------------------------------
29
30IMPLEMENT_ABSTRACT_CLASS(wxSizerItem, wxObject);
31IMPLEMENT_ABSTRACT_CLASS(wxSizer, wxObject);
f6bcfd97
BP
32IMPLEMENT_ABSTRACT_CLASS(wxGridSizer, wxSizer);
33IMPLEMENT_ABSTRACT_CLASS(wxFlexGridSizer, wxGridSizer);
0c0d686f
RD
34IMPLEMENT_ABSTRACT_CLASS(wxBoxSizer, wxSizer);
35IMPLEMENT_ABSTRACT_CLASS(wxStaticBoxSizer, wxBoxSizer);
60be2f47 36#if wxUSE_NOTEBOOK
83edc0a5 37IMPLEMENT_ABSTRACT_CLASS(wxNotebookSizer, wxSizer);
60be2f47 38#endif
0c0d686f 39
5279a24d 40//---------------------------------------------------------------------------
3417c2cd 41// wxSizerItem
5279a24d
RR
42//---------------------------------------------------------------------------
43
0c0d686f 44wxSizerItem::wxSizerItem( int width, int height, int option, int flag, int border, wxObject* userData )
5279a24d
RR
45{
46 m_window = (wxWindow *) NULL;
3417c2cd 47 m_sizer = (wxSizer *) NULL;
d597fcb7
RR
48 m_option = option;
49 m_border = border;
50 m_flag = flag;
0c0d686f
RD
51 m_userData = userData;
52
d597fcb7 53 // minimal size is the initial size
5279a24d 54 m_minSize.x = width;
c62ac5b6 55 m_minSize.y = height;
0c0d686f 56
be2577e4
RD
57 SetRatio(width, height);
58
d597fcb7
RR
59 // size is set directly
60 m_size = m_minSize;
5279a24d
RR
61}
62
0c0d686f 63wxSizerItem::wxSizerItem( wxWindow *window, int option, int flag, int border, wxObject* userData )
5279a24d
RR
64{
65 m_window = window;
3417c2cd 66 m_sizer = (wxSizer *) NULL;
5279a24d 67 m_option = option;
d597fcb7
RR
68 m_border = border;
69 m_flag = flag;
0c0d686f
RD
70 m_userData = userData;
71
d597fcb7
RR
72 // minimal size is the initial size
73 m_minSize = window->GetSize();
0c0d686f 74
be2577e4
RD
75 // aspect ratio calculated from initial size
76 SetRatio(m_minSize);
77
d597fcb7
RR
78 // size is calculated later
79 // m_size = ...
5279a24d
RR
80}
81
0c0d686f 82wxSizerItem::wxSizerItem( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
5279a24d
RR
83{
84 m_window = (wxWindow *) NULL;
85 m_sizer = sizer;
5279a24d 86 m_option = option;
d597fcb7
RR
87 m_border = border;
88 m_flag = flag;
0c0d686f
RD
89 m_userData = userData;
90
d597fcb7
RR
91 // minimal size is calculated later
92 // m_minSize = ...
be2577e4 93 m_ratio = 0;
0c0d686f 94
d597fcb7
RR
95 // size is calculated later
96 // m_size = ...
5279a24d
RR
97}
98
0c0d686f
RD
99wxSizerItem::~wxSizerItem()
100{
101 if (m_userData)
102 delete m_userData;
103 if (m_sizer)
104 delete m_sizer;
105}
106
107
3417c2cd 108wxSize wxSizerItem::GetSize()
5279a24d 109{
d597fcb7 110 wxSize ret;
3417c2cd 111 if (IsSizer())
d597fcb7
RR
112 ret = m_sizer->GetSize();
113 else
c62ac5b6 114 if (IsWindow())
d597fcb7
RR
115 ret = m_window->GetSize();
116 else ret = m_size;
0c0d686f 117
d597fcb7
RR
118 if (m_flag & wxWEST)
119 ret.x += m_border;
120 if (m_flag & wxEAST)
121 ret.x += m_border;
122 if (m_flag & wxNORTH)
123 ret.y += m_border;
124 if (m_flag & wxSOUTH)
125 ret.y += m_border;
0c0d686f 126
d597fcb7 127 return ret;
5279a24d
RR
128}
129
3417c2cd 130wxSize wxSizerItem::CalcMin()
c62ac5b6 131{
d597fcb7 132 wxSize ret;
3417c2cd 133 if (IsSizer())
be2577e4 134 {
f6bcfd97 135 ret = m_sizer->GetMinSize();
be2577e4
RD
136 // if we have to preserve aspect ratio _AND_ this is
137 // the first-time calculation, consider ret to be initial size
138 if ((m_flag & wxSHAPED) && !m_ratio) SetRatio(ret);
139 }
140
0c0d686f 141/*
d597fcb7
RR
142 The minimum size of a window should be the
143 initial size, as saved in m_minSize, not the
144 current size.
0c0d686f 145
d597fcb7 146 else
c62ac5b6 147 if (IsWindow())
d597fcb7
RR
148 ret = m_window->GetSize();
149*/
150 else ret = m_minSize;
0c0d686f 151
d597fcb7
RR
152 if (m_flag & wxWEST)
153 ret.x += m_border;
154 if (m_flag & wxEAST)
155 ret.x += m_border;
156 if (m_flag & wxNORTH)
157 ret.y += m_border;
158 if (m_flag & wxSOUTH)
159 ret.y += m_border;
0c0d686f 160
d597fcb7 161 return ret;
c62ac5b6
RR
162}
163
3417c2cd 164void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
c62ac5b6 165{
f6bcfd97 166 m_pos = pos;
3ca6a5f0 167
d597fcb7
RR
168 if (m_flag & wxWEST)
169 {
170 pos.x += m_border;
171 size.x -= m_border;
172 }
173 if (m_flag & wxEAST)
174 {
175 size.x -= m_border;
176 }
177 if (m_flag & wxNORTH)
178 {
179 pos.y += m_border;
180 size.y -= m_border;
181 }
182 if (m_flag & wxSOUTH)
183 {
184 size.y -= m_border;
185 }
be2577e4
RD
186 if (m_flag & wxSHAPED) {
187 // adjust aspect ratio
188 int rwidth = (int) (size.y * m_ratio);
189 if (rwidth > size.x) {
190 // fit horizontally
191 int rheight = (int) (size.x / m_ratio);
192 // add vertical space
193 if (m_flag & wxALIGN_CENTER_VERTICAL)
194 pos.y += (size.y - rheight) / 2;
195 else if (m_flag & wxALIGN_BOTTOM)
196 pos.y += (size.y - rheight);
197 // use reduced dimensions
198 size.y =rheight;
199 } else if (rwidth < size.x) {
200 // add horizontal space
201 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
202 pos.x += (size.x - rwidth) / 2;
203 else if (m_flag & wxALIGN_RIGHT)
204 pos.x += (size.x - rwidth);
205 size.x = rwidth;
206 }
207 }
0c0d686f 208
3417c2cd 209 if (IsSizer())
c62ac5b6 210 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
0c0d686f 211
c62ac5b6 212 if (IsWindow())
b919f007 213 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
d597fcb7
RR
214
215 m_size = size;
c62ac5b6
RR
216}
217
3417c2cd 218bool wxSizerItem::IsWindow()
5279a24d
RR
219{
220 return (m_window != NULL);
221}
222
3417c2cd 223bool wxSizerItem::IsSizer()
5279a24d
RR
224{
225 return (m_sizer != NULL);
226}
227
3417c2cd 228bool wxSizerItem::IsSpacer()
5279a24d
RR
229{
230 return (m_window == NULL) && (m_sizer == NULL);
231}
232
233//---------------------------------------------------------------------------
3417c2cd 234// wxSizer
5279a24d
RR
235//---------------------------------------------------------------------------
236
3417c2cd 237wxSizer::wxSizer()
5279a24d
RR
238{
239 m_children.DeleteContents( TRUE );
f6bcfd97
BP
240 m_minSize.x = 0;
241 m_minSize.y = 0;
5279a24d
RR
242}
243
3417c2cd 244wxSizer::~wxSizer()
5279a24d
RR
245{
246}
0c0d686f
RD
247
248void wxSizer::Add( wxWindow *window, int option, int flag, int border, wxObject* userData )
5279a24d 249{
0c0d686f 250 m_children.Append( new wxSizerItem( window, option, flag, border, userData ) );
5279a24d
RR
251}
252
0c0d686f 253void wxSizer::Add( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
5279a24d 254{
0c0d686f 255 m_children.Append( new wxSizerItem( sizer, option, flag, border, userData ) );
5279a24d
RR
256}
257
0c0d686f 258void wxSizer::Add( int width, int height, int option, int flag, int border, wxObject* userData )
5279a24d 259{
0c0d686f 260 m_children.Append( new wxSizerItem( width, height, option, flag, border, userData ) );
5279a24d
RR
261}
262
0c0d686f 263void wxSizer::Prepend( wxWindow *window, int option, int flag, int border, wxObject* userData )
42b4e99e 264{
0c0d686f 265 m_children.Insert( new wxSizerItem( window, option, flag, border, userData ) );
42b4e99e
RR
266}
267
0c0d686f 268void wxSizer::Prepend( wxSizer *sizer, int option, int flag, int border, wxObject* userData )
42b4e99e 269{
0c0d686f 270 m_children.Insert( new wxSizerItem( sizer, option, flag, border, userData ) );
42b4e99e
RR
271}
272
0c0d686f 273void wxSizer::Prepend( int width, int height, int option, int flag, int border, wxObject* userData )
42b4e99e 274{
0c0d686f 275 m_children.Insert( new wxSizerItem( width, height, option, flag, border, userData ) );
f35aa3da
RR
276}
277
278void wxSizer::Insert( int before, wxWindow *window, int option, int flag, int border, wxObject* userData )
279{
280 m_children.Insert( before, new wxSizerItem( window, option, flag, border, userData ) );
281}
282
283void wxSizer::Insert( int before, wxSizer *sizer, int option, int flag, int border, wxObject* userData )
284{
285 m_children.Insert( before, new wxSizerItem( sizer, option, flag, border, userData ) );
286}
287
288void wxSizer::Insert( int before, int width, int height, int option, int flag, int border, wxObject* userData )
289{
290 m_children.Insert( before, new wxSizerItem( width, height, option, flag, border, userData ) );
42b4e99e
RR
291}
292
293bool wxSizer::Remove( wxWindow *window )
294{
295 wxASSERT( window );
0c0d686f 296
42b4e99e
RR
297 wxNode *node = m_children.First();
298 while (node)
299 {
300 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
301 if (item->GetWindow() == window)
302 {
42b4e99e 303 m_children.DeleteNode( node );
3ca6a5f0
BP
304 return TRUE;
305 }
42b4e99e
RR
306 node = node->Next();
307 }
0c0d686f 308
42b4e99e
RR
309 return FALSE;
310}
311
312bool wxSizer::Remove( wxSizer *sizer )
313{
314 wxASSERT( sizer );
0c0d686f 315
42b4e99e
RR
316 wxNode *node = m_children.First();
317 while (node)
318 {
319 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
320 if (item->GetSizer() == sizer)
321 {
42b4e99e 322 m_children.DeleteNode( node );
3ca6a5f0
BP
323 return TRUE;
324 }
42b4e99e
RR
325 node = node->Next();
326 }
0c0d686f 327
42b4e99e
RR
328 return FALSE;
329}
330
331bool wxSizer::Remove( int pos )
332{
333 wxNode *node = m_children.Nth( pos );
334 if (!node) return FALSE;
0c0d686f 335
42b4e99e 336 m_children.DeleteNode( node );
0c0d686f 337
42b4e99e
RR
338 return TRUE;
339}
0c0d686f 340
3417c2cd 341void wxSizer::Fit( wxWindow *window )
5279a24d
RR
342{
343 window->SetSize( GetMinWindowSize( window ) );
344}
345
3417c2cd 346void wxSizer::Layout()
c62ac5b6 347{
42b4e99e 348 CalcMin();
c62ac5b6
RR
349 RecalcSizes();
350}
351
3417c2cd 352void wxSizer::SetSizeHints( wxWindow *window )
5279a24d
RR
353{
354 wxSize size( GetMinWindowSize( window ) );
355 window->SetSizeHints( size.x, size.y );
356}
357
3417c2cd 358wxSize wxSizer::GetMinWindowSize( wxWindow *window )
5279a24d 359{
77671fd2 360 wxSize minSize( GetMinSize() );
5279a24d
RR
361 wxSize size( window->GetSize() );
362 wxSize client_size( window->GetClientSize() );
77671fd2 363 return wxSize( minSize.x+size.x-client_size.x,
0c0d686f 364 minSize.y+size.y-client_size.y );
5279a24d
RR
365}
366
3417c2cd 367void wxSizer::SetDimension( int x, int y, int width, int height )
5279a24d
RR
368{
369 m_position.x = x;
370 m_position.y = y;
371 m_size.x = width;
372 m_size.y = height;
42b4e99e 373 CalcMin();
5279a24d
RR
374 RecalcSizes();
375}
376
f6bcfd97 377wxSize wxSizer::GetMinSize()
3ca6a5f0 378{
f6bcfd97
BP
379 wxSize ret( CalcMin() );
380 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
381 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
3ca6a5f0 382 return ret;
f6bcfd97
BP
383}
384
385void wxSizer::DoSetMinSize( int width, int height )
386{
387 m_minSize.x = width;
388 m_minSize.y = height;
389}
390
391bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
392{
393 wxASSERT( window );
394
395 wxNode *node = m_children.First();
396 while (node)
397 {
398 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
399 if (item->GetWindow() == window)
400 {
f6bcfd97 401 item->SetInitSize( width, height );
3ca6a5f0
BP
402 return TRUE;
403 }
f6bcfd97
BP
404 node = node->Next();
405 }
406
407 node = m_children.First();
408 while (node)
409 {
410 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
411 if (item->GetSizer())
412 {
f6bcfd97
BP
413 /* It's a sizer, so lets search recursively. */
414 if (item->GetSizer()->DoSetItemMinSize( window, width, height ))
415 {
416 /* A child sizer found the requested windw, exit. */
3ca6a5f0 417 return TRUE;
f6bcfd97 418 }
3ca6a5f0 419 }
f6bcfd97
BP
420 node = node->Next();
421 }
422
423 return FALSE;
424}
425
426bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
427{
428 wxASSERT( sizer );
429
430 wxNode *node = m_children.First();
431 while (node)
432 {
433 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
434 if (item->GetSizer() == sizer)
435 {
f6bcfd97 436 item->GetSizer()->DoSetMinSize( width, height );
3ca6a5f0
BP
437 return TRUE;
438 }
f6bcfd97
BP
439 node = node->Next();
440 }
441
442 node = m_children.First();
443 while (node)
444 {
445 wxSizerItem *item = (wxSizerItem*)node->Data();
3ca6a5f0
BP
446 if (item->GetSizer())
447 {
f6bcfd97
BP
448 /* It's a sizer, so lets search recursively. */
449 if (item->GetSizer()->DoSetItemMinSize( sizer, width, height ))
450 {
451 /* A child sizer found the requested windw, exit. */
3ca6a5f0 452 return TRUE;
f6bcfd97 453 }
3ca6a5f0 454 }
f6bcfd97
BP
455 node = node->Next();
456 }
457
458 return FALSE;
459}
460
461bool wxSizer::DoSetItemMinSize( int pos, int width, int height )
462{
463 wxNode *node = m_children.Nth( pos );
464 if (!node) return FALSE;
465
466 wxSizerItem *item = (wxSizerItem*) node->Data();
467 if (item->GetSizer())
468 {
469 /* Sizers contains the minimal size in them, if not calculated ... */
470 item->GetSizer()->DoSetMinSize( width, height );
471 }
472 else
473 {
3ca6a5f0 474 /* ... whereas the minimal size of spacers and windows in stored
f6bcfd97
BP
475 in the item */
476 item->SetInitSize( width, height );
477 }
478
479 return TRUE;
480}
481
482//---------------------------------------------------------------------------
483// wxGridSizer
484//---------------------------------------------------------------------------
485
486wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
487{
488 m_rows = rows;
489 m_cols = cols;
490 m_vgap = vgap;
491 m_hgap = hgap;
492}
493
494wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
495{
496 m_rows = 0;
497 m_cols = cols;
498 m_vgap = vgap;
499 m_hgap = hgap;
500}
501
502void wxGridSizer::RecalcSizes()
503{
504 if (m_children.GetCount() == 0)
505 return;
506
507 int nitems = m_children.GetCount();
508 int nrows = m_rows;
509 int ncols = m_cols;
510
511 if (ncols > 0)
512 nrows = (nitems + ncols-1) / ncols;
513 else
514 ncols = (nitems + nrows-1) / nrows;
515
516 wxSize sz( GetSize() );
517 wxPoint pt( GetPosition() );
3ca6a5f0
BP
518
519 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
520 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
f6bcfd97
BP
521
522 int x = pt.x;
523 for (int c = 0; c < ncols; c++)
524 {
525 int y = pt.y;
526 for (int r = 0; r < nrows; r++)
527 {
528 int i = r * ncols + c;
529 if (i < nitems)
530 {
531 wxNode *node = m_children.Nth( i );
532 wxASSERT( node );
3ca6a5f0 533
f6bcfd97
BP
534 SetItemBounds( (wxSizerItem*) node->Data(), x, y, w, h);
535 }
536 y = y + h + m_vgap;
537 }
538 x = x + w + m_hgap;
539 }
540}
541
542wxSize wxGridSizer::CalcMin()
543{
544 if (m_children.GetCount() == 0)
545 return wxSize(10,10);
546
547 int nitems = m_children.GetCount();
548 int nrows = m_rows;
549 int ncols = m_cols;
550
551 if (ncols > 0)
552 nrows = (nitems + ncols-1) / ncols;
553 else
554 ncols = (nitems + nrows-1) / nrows;
555
556 /* Find the max width and height for any component */
557 int w = 0;
558 int h = 0;
3ca6a5f0 559
f6bcfd97
BP
560 wxNode *node = m_children.First();
561 while (node)
562 {
563 wxSizerItem *item = (wxSizerItem*)node->Data();
564 wxSize sz( item->CalcMin() );
565 w = wxMax( w, sz.x );
566 h = wxMax( h, sz.y );
3ca6a5f0 567
f6bcfd97
BP
568 node = node->Next();
569 }
3ca6a5f0 570
f6bcfd97
BP
571 return wxSize(ncols * w + (ncols-1) * m_hgap,
572 nrows * h + (nrows-1) * m_vgap);
573}
574
575void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
576{
577 wxPoint pt( x,y );
578 wxSize sz( item->CalcMin() );
579 int flag = item->GetFlag();
580
581 if ((flag & wxEXPAND) || (flag & wxSHAPED))
582 {
583 sz = wxSize(w, h);
584 }
585 else
586 {
587 if (flag & wxALIGN_CENTER_HORIZONTAL)
588 {
589 pt.x = x + (w - sz.x) / 2;
590 }
591 else if (flag & wxALIGN_RIGHT)
592 {
593 pt.x = x + (w - sz.x);
594 }
3ca6a5f0 595
f6bcfd97
BP
596 if (flag & wxALIGN_CENTER_VERTICAL)
597 {
598 pt.y = y + (h - sz.y) / 2;
599 }
600 else if (flag & wxALIGN_BOTTOM)
601 {
602 pt.y = y + (h - sz.y);
603 }
604 }
3ca6a5f0 605
f6bcfd97
BP
606 item->SetDimension(pt, sz);
607}
608
609//---------------------------------------------------------------------------
610// wxFlexGridSizer
611//---------------------------------------------------------------------------
612
613wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
614 : wxGridSizer( rows, cols, vgap, hgap )
3ca6a5f0 615{
f6bcfd97
BP
616 m_rowHeights = (int*) NULL;
617 m_colWidths = (int*) NULL;
618}
619
620wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
3ca6a5f0
BP
621 : wxGridSizer( cols, vgap, hgap )
622{
f6bcfd97
BP
623 m_rowHeights = (int*) NULL;
624 m_colWidths = (int*) NULL;
625}
3ca6a5f0 626
f6bcfd97
BP
627wxFlexGridSizer::~wxFlexGridSizer()
628{
629 if (m_rowHeights)
630 delete[] m_rowHeights;
631 if (m_colWidths)
632 delete[] m_colWidths;
633}
634
635void wxFlexGridSizer::CreateArrays()
636{
637 if (m_rowHeights)
638 delete[] m_rowHeights;
639 if (m_colWidths)
640 delete[] m_colWidths;
3ca6a5f0 641
f6bcfd97
BP
642 if (m_children.GetCount() == 0)
643 return;
3ca6a5f0 644
f6bcfd97
BP
645 int nitems = m_children.GetCount();
646 int nrows = m_rows;
647 int ncols = m_cols;
648
649 if (ncols > 0)
650 nrows = (nitems + ncols-1) / ncols;
651 else
652 ncols = (nitems + nrows-1) / nrows;
653
654 m_rowHeights = new int[nrows];
655 m_colWidths = new int[ncols];
3ca6a5f0 656
f6bcfd97
BP
657 for (int col = 0; col < ncols; col++)
658 m_colWidths[ col ] = 0;
659 for (int row = 0; row < nrows; row++)
660 m_rowHeights[ row ] = 0;
661}
662
663void wxFlexGridSizer::RecalcSizes()
664{
665 if (m_children.GetCount() == 0)
666 return;
667
668 int nitems = m_children.GetCount();
669 int nrows = m_rows;
670 int ncols = m_cols;
671
672 if (ncols > 0)
673 nrows = (nitems + ncols-1) / ncols;
674 else
675 ncols = (nitems + nrows-1) / nrows;
676
677 wxSize sz( GetSize() );
678 wxSize minsz( CalcMin() );
679 wxPoint pt( GetPosition() );
680 int delta;
681 size_t idx;
682
683 if ((m_growableRows.GetCount() > 0) && (sz.y > minsz.y))
684 {
685 delta = (sz.y - minsz.y) / m_growableRows.GetCount();
686 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
687 m_rowHeights[ m_growableRows[idx] ] += delta;
688 }
3ca6a5f0 689
f6bcfd97
BP
690 if ((m_growableCols.GetCount() > 0) && (sz.x > minsz.x))
691 {
692 delta = (sz.x - minsz.x) / m_growableCols.GetCount();
693 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
694 m_colWidths[ m_growableCols[idx] ] += delta;
695 }
3ca6a5f0 696
f6bcfd97
BP
697 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
698
699 int x = pt.x;
700 for (int c = 0; c < ncols; c++)
701 {
702 int y = pt.y;
703 for (int r = 0; r < nrows; r++)
704 {
705 int i = r * ncols + c;
706 if (i < nitems)
707 {
708 wxNode *node = m_children.Nth( i );
709 wxASSERT( node );
3ca6a5f0 710
f6bcfd97
BP
711 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
712 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
3ca6a5f0 713
f6bcfd97
BP
714 SetItemBounds( (wxSizerItem*) node->Data(), x, y, w, h);
715 }
716 y = y + m_rowHeights[r] + m_vgap;
717 }
718 x = x + m_colWidths[c] + m_hgap;
719 }
720}
721
722wxSize wxFlexGridSizer::CalcMin()
723{
724 if (m_children.GetCount() == 0)
725 return wxSize(10,10);
726
727 int nitems = m_children.GetCount();
728 int nrows = m_rows;
729 int ncols = m_cols;
730
731 if (ncols > 0)
732 nrows = (nitems + ncols-1) / ncols;
733 else
734 ncols = (nitems + nrows-1) / nrows;
735
736 CreateArrays();
3ca6a5f0 737
f6bcfd97
BP
738 int col;
739 int row;
3ca6a5f0 740
f6bcfd97
BP
741 int i = 0;
742 wxNode *node = m_children.First();
743 while (node)
744 {
745 wxSizerItem *item = (wxSizerItem*)node->Data();
746 wxSize sz( item->CalcMin() );
747 row = i / ncols;
748 col = i % ncols;
749 m_rowHeights[ row ] = wxMax( sz.y, m_rowHeights[ row ] );
750 m_colWidths[ col ] = wxMax( sz.x, m_colWidths[ col ] );
3ca6a5f0 751
f6bcfd97
BP
752 node = node->Next();
753 i++;
754 }
3ca6a5f0 755
f6bcfd97
BP
756 int width = 0;
757 for (col = 0; col < ncols; col++)
758 width += m_colWidths[ col ];
3ca6a5f0 759
f6bcfd97
BP
760 int height = 0;
761 for (row = 0; row < nrows; row++)
762 height += m_rowHeights[ row ];
3ca6a5f0 763
f6bcfd97
BP
764 return wxSize( width + (ncols-1) * m_hgap,
765 height + (nrows-1) * m_vgap);
766}
767
768void wxFlexGridSizer::AddGrowableRow( size_t idx )
769{
770 m_growableRows.Add( idx );
771}
772
3ca6a5f0 773void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx) )
f6bcfd97
BP
774{
775}
776
777void wxFlexGridSizer::AddGrowableCol( size_t idx )
778{
779 m_growableCols.Add( idx );
780}
781
3ca6a5f0 782void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx) )
f6bcfd97
BP
783{
784}
785
c62ac5b6 786//---------------------------------------------------------------------------
92afa2b1 787// wxBoxSizer
61d514bb
RR
788//---------------------------------------------------------------------------
789
92afa2b1 790wxBoxSizer::wxBoxSizer( int orient )
61d514bb
RR
791{
792 m_orient = orient;
793}
794
92afa2b1 795void wxBoxSizer::RecalcSizes()
61d514bb
RR
796{
797 if (m_children.GetCount() == 0)
61d514bb 798 return;
0c0d686f 799
61d514bb
RR
800 int delta = 0;
801 int extra = 0;
802 if (m_stretchable)
803 {
804 if (m_orient == wxHORIZONTAL)
805 {
806 delta = (m_size.x - m_fixedWidth) / m_stretchable;
807 extra = (m_size.x - m_fixedWidth) % m_stretchable;
3ca6a5f0
BP
808 }
809 else
810 {
61d514bb
RR
811 delta = (m_size.y - m_fixedHeight) / m_stretchable;
812 extra = (m_size.y - m_fixedHeight) % m_stretchable;
3ca6a5f0 813 }
61d514bb 814 }
0c0d686f 815
61d514bb 816 wxPoint pt( m_position );
0c0d686f 817
61d514bb
RR
818 wxNode *node = m_children.GetFirst();
819 while (node)
820 {
3417c2cd 821 wxSizerItem *item = (wxSizerItem*) node->Data();
61d514bb 822
3ca6a5f0
BP
823 int weight = 1;
824 if (item->GetOption())
825 weight = item->GetOption();
826
827 wxSize size( item->CalcMin() );
828
829 if (m_orient == wxVERTICAL)
830 {
831 wxCoord height = size.y;
832 if (item->GetOption())
833 {
834 height = (delta * weight) + extra;
835 extra = 0; // only the first item will get the remainder as extra size
836 }
837
838 wxPoint child_pos( pt );
839 wxSize child_size( wxSize( size.x, height) );
840
841 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
842 child_size.x = m_size.x;
843 else if (item->GetFlag() & wxALIGN_RIGHT)
844 child_pos.x += m_size.x - size.x;
845 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
846 // XXX wxCENTER is added for backward compatibility;
847 // wxALIGN_CENTER should be used in new code
848 child_pos.x += (m_size.x - size.x) / 2;
849
850 item->SetDimension( child_pos, child_size );
851
852 pt.y += height;
853 }
854 else
855 {
856 wxCoord width = size.x;
857 if (item->GetOption())
858 {
859 width = (delta * weight) + extra;
860 extra = 0; // only the first item will get the remainder as extra size
861 }
862
863 wxPoint child_pos( pt );
864 wxSize child_size( wxSize(width, size.y) );
865
866 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
867 child_size.y = m_size.y;
868 else if (item->GetFlag() & wxALIGN_BOTTOM)
869 child_pos.y += m_size.y - size.y;
870 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
871 // XXX wxCENTER is added for backward compatibility;
872 // wxALIGN_CENTER should be used in new code
873 child_pos.y += (m_size.y - size.y) / 2;
874
875 item->SetDimension( child_pos, child_size );
876
877 pt.x += width;
878 }
879
880 node = node->Next();
61d514bb
RR
881 }
882}
883
92afa2b1 884wxSize wxBoxSizer::CalcMin()
61d514bb
RR
885{
886 if (m_children.GetCount() == 0)
c7a9fa36 887 return wxSize(10,10);
0c0d686f 888
61d514bb
RR
889 m_stretchable = 0;
890 m_minWidth = 0;
891 m_minHeight = 0;
892 m_fixedWidth = 0;
893 m_fixedHeight = 0;
0c0d686f 894
61d514bb
RR
895 wxNode *node = m_children.GetFirst();
896 while (node)
897 {
3417c2cd 898 wxSizerItem *item = (wxSizerItem*) node->Data();
0c0d686f 899
aa21b509
RR
900 m_stretchable += item->GetOption();
901
3ca6a5f0
BP
902 wxSize size( item->CalcMin() );
903
904 if (m_orient == wxHORIZONTAL)
905 {
aa21b509 906 m_minWidth += size.x;
3ca6a5f0
BP
907 m_minHeight = wxMax( m_minHeight, size.y );
908 }
909 else
910 {
aa21b509 911 m_minHeight += size.y;
3ca6a5f0
BP
912 m_minWidth = wxMax( m_minWidth, size.x );
913 }
914
aa21b509 915 if (item->GetOption() == 0)
3ca6a5f0
BP
916 {
917 if (m_orient == wxVERTICAL)
918 {
919 m_fixedHeight += size.y;
920 m_fixedWidth = wxMax( m_fixedWidth, size.x );
921 }
922 else
aa21b509 923 {
3ca6a5f0
BP
924 m_fixedWidth += size.x;
925 m_fixedHeight = wxMax( m_fixedHeight, size.y );
926 }
927 }
928
929 node = node->Next();
61d514bb 930 }
0c0d686f 931
61d514bb
RR
932 return wxSize( m_minWidth, m_minHeight );
933}
27ea1d8a
RR
934
935//---------------------------------------------------------------------------
936// wxStaticBoxSizer
937//---------------------------------------------------------------------------
938
939wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
940 : wxBoxSizer( orient )
941{
223d09f6 942 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
0c0d686f 943
27ea1d8a
RR
944 m_staticBox = box;
945}
0c0d686f 946
27ea1d8a
RR
947void wxStaticBoxSizer::RecalcSizes()
948{
949 // this will have to be done platform by platform
950 // as there is no way to guess the thickness of
951 // a wxStaticBox border
952 int top_border = 15;
953 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
954 int other_border = 5;
955
956 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
0c0d686f 957
27ea1d8a
RR
958 wxPoint old_pos( m_position );
959 m_position.x += other_border;
960 m_position.y += top_border;
961 wxSize old_size( m_size );
962 m_size.x -= 2*other_border;
963 m_size.y -= top_border + other_border;
0c0d686f 964
27ea1d8a 965 wxBoxSizer::RecalcSizes();
0c0d686f 966
27ea1d8a
RR
967 m_position = old_pos;
968 m_size = old_size;
969}
970
971wxSize wxStaticBoxSizer::CalcMin()
972{
83edc0a5 973 // This will have to be done platform by platform
27ea1d8a 974 // as there is no way to guess the thickness of
83edc0a5 975 // a wxStaticBox border.
3ca6a5f0 976
27ea1d8a
RR
977 int top_border = 15;
978 if (m_staticBox->GetLabel().IsEmpty()) top_border = 5;
979 int other_border = 5;
0c0d686f 980
27ea1d8a 981 wxSize ret( wxBoxSizer::CalcMin() );
cae31b8b 982 ret.x += 2*other_border;
27ea1d8a 983 ret.y += other_border + top_border;
0c0d686f 984
27ea1d8a
RR
985 return ret;
986}
83edc0a5
RR
987
988//---------------------------------------------------------------------------
989// wxNotebookSizer
990//---------------------------------------------------------------------------
991
60be2f47
VS
992#if wxUSE_NOTEBOOK
993
83edc0a5
RR
994wxNotebookSizer::wxNotebookSizer( wxNotebook *nb )
995{
996 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a notebook") );
3ca6a5f0 997
83edc0a5
RR
998 m_notebook = nb;
999}
1000
1001void wxNotebookSizer::RecalcSizes()
1002{
1003 m_notebook->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1004}
1005
1006wxSize wxNotebookSizer::CalcMin()
1007{
1008 // This will have to be done platform by platform
1009 // as there is no way to guess the thickness of
1010 // the wxNotebook tabs and border.
3ca6a5f0 1011
83edc0a5
RR
1012 int borderX = 5;
1013 int borderY = 5;
1014 if ((m_notebook->HasFlag(wxNB_RIGHT)) ||
1015 (m_notebook->HasFlag(wxNB_LEFT)))
1016 {
f6bcfd97 1017 borderX += 90; // improvements later..
83edc0a5
RR
1018 }
1019 else
1020 {
f6bcfd97 1021 borderY += 40; // improvements later..
83edc0a5 1022 }
3ca6a5f0 1023
83edc0a5
RR
1024 if (m_notebook->GetChildren().GetCount() == 0)
1025 return wxSize(borderX + 10, borderY + 10);
1026
1027 int maxX = 0;
1028 int maxY = 0;
1029
1030 wxWindowList::Node *node = m_notebook->GetChildren().GetFirst();
1031 while (node)
1032 {
1033 wxWindow *item = node->GetData();
3ca6a5f0
BP
1034 wxSizer *itemsizer = item->GetSizer();
1035
1036 if (itemsizer)
1037 {
83edc0a5 1038 wxSize subsize( itemsizer->CalcMin() );
83edc0a5 1039
3ca6a5f0
BP
1040 if (subsize.x > maxX) maxX = subsize.x;
1041 if (subsize.y > maxY) maxY = subsize.y;
1042 }
1043
1044 node = node->GetNext();
83edc0a5
RR
1045 }
1046
1047 return wxSize( borderX + maxX, borderY + maxY );
1048}
1049
60be2f47 1050#endif // wxUSE_NOTEBOOK