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