]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
made all Add/Insert/Prepend methods inline
[wxWidgets.git] / src / common / sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sizer.cpp
3 // Purpose: provide new wxSizer class for layout
4 // Author: Robert Roebling and Robin Dunn, contributions by
5 // Dirk Holtwick, Ron Lee
6 // Modified by: Ron Lee
7 // Created:
8 // RCS-ID: $Id$
9 // Copyright: (c) Robin Dunn, Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "sizer.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "wx/sizer.h"
25 #include "wx/utils.h"
26 #include "wx/statbox.h"
27 #include "wx/listimpl.cpp"
28 #if WXWIN_COMPATIBILITY_2_4
29 #include "wx/notebook.h"
30 #endif
31
32 #ifdef __WXMAC__
33 # include "wx/mac/uma.h"
34 #endif
35
36 //---------------------------------------------------------------------------
37
38 IMPLEMENT_CLASS(wxSizerItem, wxObject)
39 IMPLEMENT_CLASS(wxSizer, wxObject)
40 IMPLEMENT_CLASS(wxGridSizer, wxSizer)
41 IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
42 IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
43 #if wxUSE_STATBOX
44 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
45 #endif
46
47 WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
48
49 /*
50 TODO PROPERTIES
51 sizeritem
52 object
53 object_ref
54 minsize
55 option
56 flag
57 border
58 spacer
59 option
60 flag
61 borfder
62 boxsizer
63 orient
64 staticboxsizer
65 orient
66 label
67 gridsizer
68 rows
69 cols
70 vgap
71 hgap
72 flexgridsizer
73 rows
74 cols
75 vgap
76 hgap
77 growablerows
78 growablecols
79 minsize
80 */
81 //---------------------------------------------------------------------------
82 // wxSizerItem
83 //---------------------------------------------------------------------------
84
85 wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
86 : m_window( NULL )
87 , m_sizer( NULL )
88 , m_size( wxSize( width, height ) ) // size is set directly
89 , m_minSize( m_size ) // minimal size is the initial size
90 , m_proportion( proportion )
91 , m_border( border )
92 , m_flag( flag )
93 , m_show( true )
94 , m_userData( userData )
95 {
96 SetRatio( m_size );
97 }
98
99 wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
100 : m_window( window )
101 , m_sizer( NULL )
102 , m_proportion( proportion )
103 , m_border( border )
104 , m_flag( flag )
105 , m_show( true )
106 , m_userData( userData )
107 {
108 if (flag & wxFIXED_MINSIZE)
109 window->SetMinSize(window->GetSize());
110 m_minSize = window->GetSize();
111
112 // aspect ratio calculated from initial size
113 SetRatio( m_minSize );
114
115 // m_size is calculated later
116 }
117
118 wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
119 : m_window( NULL )
120 , m_sizer( sizer )
121 , m_proportion( proportion )
122 , m_border( border )
123 , m_flag( flag )
124 , m_show( true )
125 , m_ratio( 0.0 )
126 , m_userData( userData )
127 {
128 // m_minSize is calculated later
129 // m_size is calculated later
130 }
131
132 wxSizerItem::wxSizerItem()
133 : m_window( NULL )
134 , m_sizer( NULL )
135 , m_proportion( 0 )
136 , m_border( 0 )
137 , m_flag( 0 )
138 , m_show( true )
139 , m_ratio( 0.0 )
140 , m_userData( NULL )
141 {
142 }
143
144 wxSizerItem::~wxSizerItem()
145 {
146 delete m_userData;
147
148 if ( m_window )
149 {
150 m_window->SetContainingSizer(NULL);
151 }
152 else // we must be a sizer
153 {
154 delete m_sizer;
155 }
156 }
157
158
159 wxSize wxSizerItem::GetSize() const
160 {
161 wxSize ret;
162 if (IsSizer())
163 ret = m_sizer->GetSize();
164 else
165 if (IsWindow())
166 ret = m_window->GetSize();
167 else ret = m_size;
168
169 if (m_flag & wxWEST)
170 ret.x += m_border;
171 if (m_flag & wxEAST)
172 ret.x += m_border;
173 if (m_flag & wxNORTH)
174 ret.y += m_border;
175 if (m_flag & wxSOUTH)
176 ret.y += m_border;
177
178 return ret;
179 }
180
181 wxSize wxSizerItem::CalcMin()
182 {
183 if (IsSizer())
184 {
185 m_minSize = m_sizer->GetMinSize();
186
187 // if we have to preserve aspect ratio _AND_ this is
188 // the first-time calculation, consider ret to be initial size
189 if ((m_flag & wxSHAPED) && !m_ratio)
190 SetRatio(m_minSize);
191 }
192 else if ( IsWindow() )
193 {
194 // Since the size of the window may change during runtime, we
195 // should use the current minimal/best size.
196 m_minSize = m_window->GetBestFittingSize();
197 }
198
199 return GetMinSizeWithBorder();
200 }
201
202 wxSize wxSizerItem::GetMinSizeWithBorder() const
203 {
204 wxSize ret = m_minSize;
205
206 if (m_flag & wxWEST)
207 ret.x += m_border;
208 if (m_flag & wxEAST)
209 ret.x += m_border;
210 if (m_flag & wxNORTH)
211 ret.y += m_border;
212 if (m_flag & wxSOUTH)
213 ret.y += m_border;
214
215 return ret;
216 }
217
218
219 void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
220 {
221 if (m_flag & wxSHAPED)
222 {
223 // adjust aspect ratio
224 int rwidth = (int) (size.y * m_ratio);
225 if (rwidth > size.x)
226 {
227 // fit horizontally
228 int rheight = (int) (size.x / m_ratio);
229 // add vertical space
230 if (m_flag & wxALIGN_CENTER_VERTICAL)
231 pos.y += (size.y - rheight) / 2;
232 else if (m_flag & wxALIGN_BOTTOM)
233 pos.y += (size.y - rheight);
234 // use reduced dimensions
235 size.y =rheight;
236 }
237 else if (rwidth < size.x)
238 {
239 // add horizontal space
240 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
241 pos.x += (size.x - rwidth) / 2;
242 else if (m_flag & wxALIGN_RIGHT)
243 pos.x += (size.x - rwidth);
244 size.x = rwidth;
245 }
246 }
247
248 // This is what GetPosition() returns. Since we calculate
249 // borders afterwards, GetPosition() will be the left/top
250 // corner of the surrounding border.
251 m_pos = pos;
252
253 if (m_flag & wxWEST)
254 {
255 pos.x += m_border;
256 size.x -= m_border;
257 }
258 if (m_flag & wxEAST)
259 {
260 size.x -= m_border;
261 }
262 if (m_flag & wxNORTH)
263 {
264 pos.y += m_border;
265 size.y -= m_border;
266 }
267 if (m_flag & wxSOUTH)
268 {
269 size.y -= m_border;
270 }
271
272 if (IsSizer())
273 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
274
275 if (IsWindow())
276 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
277
278 m_size = size;
279 }
280
281 void wxSizerItem::DeleteWindows()
282 {
283 if (m_window)
284 {
285 m_window->Destroy();
286 m_window = NULL;
287 }
288
289 if (m_sizer)
290 m_sizer->DeleteWindows();
291 }
292
293 bool wxSizerItem::IsWindow() const
294 {
295 return (m_window != NULL);
296 }
297
298 bool wxSizerItem::IsSizer() const
299 {
300 return (m_sizer != NULL);
301 }
302
303 bool wxSizerItem::IsSpacer() const
304 {
305 return (m_window == NULL) && (m_sizer == NULL);
306 }
307
308 void wxSizerItem::Show( bool show )
309 {
310 m_show = show;
311
312 if( IsWindow() )
313 m_window->Show( show );
314 else if( IsSizer() )
315 m_sizer->ShowItems( show );
316
317 // ... nothing else to do to hide/show spacers
318 }
319
320 void wxSizerItem::SetOption( int option )
321 {
322 SetProportion( option );
323 }
324
325 int wxSizerItem::GetOption() const
326 {
327 return GetProportion();
328 }
329
330
331 //---------------------------------------------------------------------------
332 // wxSizer
333 //---------------------------------------------------------------------------
334
335 wxSizer::wxSizer()
336 : m_minSize( wxSize( 0, 0 ) )
337 {
338 }
339
340 wxSizer::~wxSizer()
341 {
342 WX_CLEAR_LIST(wxSizerItemList, m_children);
343 }
344
345 void wxSizer::Insert( size_t index, wxSizerItem *item )
346 {
347 m_children.Insert( index, item );
348
349 if( item->GetWindow() )
350 item->GetWindow()->SetContainingSizer( this );
351 }
352
353 bool wxSizer::Remove( wxWindow *window )
354 {
355 return Detach( window );
356 }
357
358 bool wxSizer::Remove( wxSizer *sizer )
359 {
360 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
361
362 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
363 while (node)
364 {
365 wxSizerItem *item = node->GetData();
366
367 if (item->GetSizer() == sizer)
368 {
369 delete item;
370 m_children.Erase( node );
371 return true;
372 }
373
374 node = node->GetNext();
375 }
376
377 return false;
378 }
379
380 bool wxSizer::Remove( int index )
381 {
382 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
383 false,
384 _T("Remove index is out of range") );
385
386 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
387
388 wxCHECK_MSG( node, false, _T("Failed to find child node") );
389
390 wxSizerItem *item = node->GetData();
391
392 if( item->IsWindow() )
393 item->GetWindow()->SetContainingSizer( NULL );
394
395 delete item;
396 m_children.Erase( node );
397 return true;
398 }
399
400 bool wxSizer::Detach( wxSizer *sizer )
401 {
402 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
403
404 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
405 while (node)
406 {
407 wxSizerItem *item = node->GetData();
408
409 if (item->GetSizer() == sizer)
410 {
411 item->DetachSizer();
412 delete item;
413 m_children.Erase( node );
414 return true;
415 }
416 node = node->GetNext();
417 }
418
419 return false;
420 }
421
422 bool wxSizer::Detach( wxWindow *window )
423 {
424 wxASSERT_MSG( window, _T("Detaching NULL window") );
425
426 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
427 while (node)
428 {
429 wxSizerItem *item = node->GetData();
430
431 if (item->GetWindow() == window)
432 {
433 item->GetWindow()->SetContainingSizer( NULL );
434 delete item;
435 m_children.Erase( node );
436 return true;
437 }
438 node = node->GetNext();
439 }
440
441 return false;
442 }
443
444 bool wxSizer::Detach( int index )
445 {
446 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
447 false,
448 _T("Detach index is out of range") );
449
450 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
451
452 wxCHECK_MSG( node, false, _T("Failed to find child node") );
453
454 wxSizerItem *item = node->GetData();
455
456 if( item->IsSizer() )
457 item->DetachSizer();
458 else if( item->IsWindow() )
459 item->GetWindow()->SetContainingSizer( NULL );
460
461 delete item;
462 m_children.Erase( node );
463 return true;
464 }
465
466 void wxSizer::Clear( bool delete_windows )
467 {
468 // First clear the ContainingSizer pointers
469 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
470 while (node)
471 {
472 wxSizerItem *item = node->GetData();
473
474 if (item->IsWindow())
475 item->GetWindow()->SetContainingSizer( NULL );
476 node = node->GetNext();
477 }
478
479 // Destroy the windows if needed
480 if (delete_windows)
481 DeleteWindows();
482
483 // Now empty the list
484 WX_CLEAR_LIST(wxSizerItemList, m_children);
485 }
486
487 void wxSizer::DeleteWindows()
488 {
489 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
490 while (node)
491 {
492 wxSizerItem *item = node->GetData();
493
494 item->DeleteWindows();
495 node = node->GetNext();
496 }
497 }
498
499 wxSize wxSizer::Fit( wxWindow *window )
500 {
501 wxSize size(window->IsTopLevel() ? FitSize(window)
502 : GetMinWindowSize(window));
503
504 window->SetSize( size );
505
506 return size;
507 }
508
509 void wxSizer::FitInside( wxWindow *window )
510 {
511 wxSize size;
512 if (window->IsTopLevel())
513 size = VirtualFitSize( window );
514 else
515 size = GetMinClientSize( window );
516
517 window->SetVirtualSize( size );
518 }
519
520 void wxSizer::Layout()
521 {
522 // (re)calculates minimums needed for each item and other preparations
523 // for layout
524 CalcMin();
525
526 // Applies the layout and repositions/resizes the items
527 RecalcSizes();
528 }
529
530 void wxSizer::SetSizeHints( wxWindow *window )
531 {
532 // Preserve the window's max size hints, but set the
533 // lower bound according to the sizer calculations.
534
535 wxSize size = Fit( window );
536
537 window->SetSizeHints( size.x,
538 size.y,
539 window->GetMaxWidth(),
540 window->GetMaxHeight() );
541 }
542
543 void wxSizer::SetVirtualSizeHints( wxWindow *window )
544 {
545 // Preserve the window's max size hints, but set the
546 // lower bound according to the sizer calculations.
547
548 FitInside( window );
549 wxSize size( window->GetVirtualSize() );
550 window->SetVirtualSizeHints( size.x,
551 size.y,
552 window->GetMaxWidth(),
553 window->GetMaxHeight() );
554 }
555
556 wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
557 {
558 return window->GetMaxSize();
559 }
560
561 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
562 {
563 wxSize minSize( GetMinSize() );
564 wxSize size( window->GetSize() );
565 wxSize client_size( window->GetClientSize() );
566
567 return wxSize( minSize.x+size.x-client_size.x,
568 minSize.y+size.y-client_size.y );
569 }
570
571 // TODO on mac we need a function that determines how much free space this
572 // min size contains, in order to make sure that we have 20 pixels of free
573 // space around the controls
574
575 // Return a window size that will fit within the screens dimensions
576 wxSize wxSizer::FitSize( wxWindow *window )
577 {
578 wxSize size = GetMinWindowSize( window );
579 wxSize sizeMax = GetMaxWindowSize( window );
580
581 // Limit the size if sizeMax != wxDefaultSize
582
583 if ( size.x > sizeMax.x && sizeMax.x != -1 )
584 size.x = sizeMax.x;
585 if ( size.y > sizeMax.y && sizeMax.y != -1 )
586 size.y = sizeMax.y;
587
588 return size;
589 }
590
591 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
592 {
593 wxSize maxSize( window->GetMaxSize() );
594
595 if( maxSize != wxDefaultSize )
596 {
597 wxSize size( window->GetSize() );
598 wxSize client_size( window->GetClientSize() );
599
600 return wxSize( maxSize.x + client_size.x - size.x,
601 maxSize.y + client_size.y - size.y );
602 }
603 else
604 return wxDefaultSize;
605 }
606
607 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
608 {
609 return GetMinSize(); // Already returns client size.
610 }
611
612 wxSize wxSizer::VirtualFitSize( wxWindow *window )
613 {
614 wxSize size = GetMinClientSize( window );
615 wxSize sizeMax = GetMaxClientSize( window );
616
617 // Limit the size if sizeMax != wxDefaultSize
618
619 if ( size.x > sizeMax.x && sizeMax.x != -1 )
620 size.x = sizeMax.x;
621 if ( size.y > sizeMax.y && sizeMax.y != -1 )
622 size.y = sizeMax.y;
623
624 return size;
625 }
626
627 void wxSizer::SetDimension( int x, int y, int width, int height )
628 {
629 m_position.x = x;
630 m_position.y = y;
631 m_size.x = width;
632 m_size.y = height;
633 Layout();
634 }
635
636 wxSize wxSizer::GetMinSize()
637 {
638 wxSize ret( CalcMin() );
639 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
640 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
641 return ret;
642 }
643
644 void wxSizer::DoSetMinSize( int width, int height )
645 {
646 m_minSize.x = width;
647 m_minSize.y = height;
648 }
649
650 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
651 {
652 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
653
654 // Is it our immediate child?
655
656 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
657 while (node)
658 {
659 wxSizerItem *item = node->GetData();
660
661 if (item->GetWindow() == window)
662 {
663 item->SetMinSize( width, height );
664 return true;
665 }
666 node = node->GetNext();
667 }
668
669 // No? Search any subsizers we own then
670
671 node = m_children.GetFirst();
672 while (node)
673 {
674 wxSizerItem *item = node->GetData();
675
676 if ( item->GetSizer() &&
677 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
678 {
679 // A child sizer found the requested windw, exit.
680 return true;
681 }
682 node = node->GetNext();
683 }
684
685 return false;
686 }
687
688 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
689 {
690 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
691
692 // Is it our immediate child?
693
694 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
695 while (node)
696 {
697 wxSizerItem *item = node->GetData();
698
699 if (item->GetSizer() == sizer)
700 {
701 item->GetSizer()->DoSetMinSize( width, height );
702 return true;
703 }
704 node = node->GetNext();
705 }
706
707 // No? Search any subsizers we own then
708
709 node = m_children.GetFirst();
710 while (node)
711 {
712 wxSizerItem *item = node->GetData();
713
714 if ( item->GetSizer() &&
715 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
716 {
717 // A child found the requested sizer, exit.
718 return true;
719 }
720 node = node->GetNext();
721 }
722
723 return false;
724 }
725
726 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
727 {
728 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
729
730 wxCHECK_MSG( node, false, _T("Failed to find child node") );
731
732 wxSizerItem *item = node->GetData();
733
734 if (item->GetSizer())
735 {
736 // Sizers contains the minimal size in them, if not calculated ...
737 item->GetSizer()->DoSetMinSize( width, height );
738 }
739 else
740 {
741 // ... but the minimal size of spacers and windows is stored via the item
742 item->SetMinSize( width, height );
743 }
744
745 return true;
746 }
747
748 bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
749 {
750 wxASSERT_MSG( window, _T("Show for NULL window") );
751
752 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
753 while (node)
754 {
755 wxSizerItem *item = node->GetData();
756
757 if (item->GetWindow() == window)
758 {
759 item->Show( show );
760
761 return true;
762 }
763 else if (recursive && item->IsSizer())
764 {
765 if (item->GetSizer()->Show(window, show, recursive))
766 return true;
767 }
768
769 node = node->GetNext();
770 }
771
772 return false;
773 }
774
775 bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
776 {
777 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
778
779 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
780 while (node)
781 {
782 wxSizerItem *item = node->GetData();
783
784 if (item->GetSizer() == sizer)
785 {
786 item->Show( show );
787
788 return true;
789 }
790 else if (recursive && item->IsSizer())
791 {
792 if (item->GetSizer()->Show(sizer, show, recursive))
793 return true;
794 }
795
796 node = node->GetNext();
797 }
798
799 return false;
800 }
801
802 bool wxSizer::Show( size_t index, bool show)
803 {
804 wxCHECK_MSG( index < m_children.GetCount(),
805 false,
806 _T("Show index is out of range") );
807
808 m_children.Item( index )->GetData()->Show( show );
809
810 return true;
811 }
812
813 void wxSizer::ShowItems( bool show )
814 {
815 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
816 while (node)
817 {
818 node->GetData()->Show( show );
819 node = node->GetNext();
820 }
821 }
822
823 bool wxSizer::IsShown( wxWindow *window ) const
824 {
825 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
826 while (node)
827 {
828 wxSizerItem *item = node->GetData();
829
830 if (item->GetWindow() == window)
831 {
832 return item->IsShown();
833 }
834 node = node->GetNext();
835 }
836
837 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
838
839 return false;
840 }
841
842 bool wxSizer::IsShown( wxSizer *sizer ) const
843 {
844 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
845 while (node)
846 {
847 wxSizerItem *item = node->GetData();
848
849 if (item->GetSizer() == sizer)
850 {
851 return item->IsShown();
852 }
853 node = node->GetNext();
854 }
855
856 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
857
858 return false;
859 }
860
861 bool wxSizer::IsShown( size_t index ) const
862 {
863 wxCHECK_MSG( index < m_children.GetCount(),
864 false,
865 _T("IsShown index is out of range") );
866
867 return m_children.Item( index )->GetData()->IsShown();
868 }
869
870
871 //---------------------------------------------------------------------------
872 // wxGridSizer
873 //---------------------------------------------------------------------------
874
875 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
876 : m_rows( rows )
877 , m_cols( cols )
878 , m_vgap( vgap )
879 , m_hgap( hgap )
880 {
881 if (m_rows == 0 && m_cols == 0)
882 m_rows = 1;
883 }
884
885 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
886 : m_rows( 0 )
887 , m_cols( cols )
888 , m_vgap( vgap )
889 , m_hgap( hgap )
890 {
891 if (m_rows == 0 && m_cols == 0)
892 m_rows = 1;
893 }
894
895 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
896 {
897 int nitems = m_children.GetCount();
898 if ( nitems)
899 {
900 if ( m_cols )
901 {
902 ncols = m_cols;
903 nrows = (nitems + m_cols - 1) / m_cols;
904 }
905 else if ( m_rows )
906 {
907 ncols = (nitems + m_rows - 1) / m_rows;
908 nrows = m_rows;
909 }
910 else // 0 columns, 0 rows?
911 {
912 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
913
914 nrows = ncols = 0;
915 }
916 }
917
918 return nitems;
919 }
920
921 void wxGridSizer::RecalcSizes()
922 {
923 int nitems, nrows, ncols;
924 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
925 return;
926
927 wxSize sz( GetSize() );
928 wxPoint pt( GetPosition() );
929
930 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
931 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
932
933 int x = pt.x;
934 for (int c = 0; c < ncols; c++)
935 {
936 int y = pt.y;
937 for (int r = 0; r < nrows; r++)
938 {
939 int i = r * ncols + c;
940 if (i < nitems)
941 {
942 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
943
944 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
945
946 SetItemBounds( node->GetData(), x, y, w, h);
947 }
948 y = y + h + m_vgap;
949 }
950 x = x + w + m_hgap;
951 }
952 }
953
954 wxSize wxGridSizer::CalcMin()
955 {
956 int nrows, ncols;
957 if ( CalcRowsCols(nrows, ncols) == 0 )
958 return wxSize(10, 10);
959
960 // Find the max width and height for any component
961 int w = 0;
962 int h = 0;
963
964 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
965 while (node)
966 {
967 wxSizerItem *item = node->GetData();
968 wxSize sz( item->CalcMin() );
969
970 w = wxMax( w, sz.x );
971 h = wxMax( h, sz.y );
972
973 node = node->GetNext();
974 }
975
976 return wxSize( ncols * w + (ncols-1) * m_hgap,
977 nrows * h + (nrows-1) * m_vgap );
978 }
979
980 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
981 {
982 wxPoint pt( x,y );
983 wxSize sz( item->GetMinSizeWithBorder() );
984 int flag = item->GetFlag();
985
986 if ((flag & wxEXPAND) || (flag & wxSHAPED))
987 {
988 sz = wxSize(w, h);
989 }
990 else
991 {
992 if (flag & wxALIGN_CENTER_HORIZONTAL)
993 {
994 pt.x = x + (w - sz.x) / 2;
995 }
996 else if (flag & wxALIGN_RIGHT)
997 {
998 pt.x = x + (w - sz.x);
999 }
1000
1001 if (flag & wxALIGN_CENTER_VERTICAL)
1002 {
1003 pt.y = y + (h - sz.y) / 2;
1004 }
1005 else if (flag & wxALIGN_BOTTOM)
1006 {
1007 pt.y = y + (h - sz.y);
1008 }
1009 }
1010
1011 item->SetDimension(pt, sz);
1012 }
1013
1014 //---------------------------------------------------------------------------
1015 // wxFlexGridSizer
1016 //---------------------------------------------------------------------------
1017
1018 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1019 : wxGridSizer( rows, cols, vgap, hgap ),
1020 m_flexDirection(wxBOTH),
1021 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1022 {
1023 }
1024
1025 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1026 : wxGridSizer( cols, vgap, hgap ),
1027 m_flexDirection(wxBOTH),
1028 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1029 {
1030 }
1031
1032 wxFlexGridSizer::~wxFlexGridSizer()
1033 {
1034 }
1035
1036 void wxFlexGridSizer::RecalcSizes()
1037 {
1038 int nitems, nrows, ncols;
1039 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1040 return;
1041
1042 wxPoint pt( GetPosition() );
1043 wxSize sz( GetSize() );
1044
1045 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
1046
1047 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1048
1049 int x = pt.x;
1050 for (int c = 0; c < ncols; c++)
1051 {
1052 int y = pt.y;
1053 for (int r = 0; r < nrows; r++)
1054 {
1055 int i = r * ncols + c;
1056 if (i < nitems)
1057 {
1058 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1059
1060 wxASSERT_MSG( node, _T("Failed to find node") );
1061
1062 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1063 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1064
1065 SetItemBounds( node->GetData(), x, y, w, h);
1066 }
1067 y = y + m_rowHeights[r] + m_vgap;
1068 }
1069 x = x + m_colWidths[c] + m_hgap;
1070 }
1071 }
1072
1073 wxSize wxFlexGridSizer::CalcMin()
1074 {
1075 int nrows,
1076 ncols;
1077 size_t i, s;
1078
1079 // Number of rows/columns can change as items are added or removed.
1080 if ( !CalcRowsCols(nrows, ncols) )
1081 return wxSize(10, 10);
1082
1083 m_rowHeights.SetCount(nrows);
1084 m_colWidths.SetCount(ncols);
1085
1086 // We have to recalcuate the sizes in case the item minimum size has
1087 // changed since the previous layout, or the item has been hidden using
1088 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1089 // dimension of the row/column will be -1, indicating that the column
1090 // itself is hidden.
1091 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1092 m_rowHeights[ i ] = -1;
1093 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1094 m_colWidths[ i ] = -1;
1095
1096 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1097
1098 i = 0;
1099 while (node)
1100 {
1101 wxSizerItem *item = node->GetData();
1102 if ( item->IsShown() )
1103 {
1104 wxSize sz( item->CalcMin() );
1105 int row = i / ncols;
1106 int col = i % ncols;
1107
1108 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1109 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1110 }
1111
1112 node = node->GetNext();
1113 i++;
1114 }
1115
1116 AdjustForFlexDirection();
1117
1118 // Sum total minimum size, including gaps between rows/columns.
1119 // -1 is used as a magic number meaning empty column.
1120 int width = 0;
1121 for (int col = 0; col < ncols; col++)
1122 if ( m_colWidths[ col ] != -1 )
1123 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1124
1125 int height = 0;
1126 for (int row = 0; row < nrows; row++)
1127 if ( m_rowHeights[ row ] != -1 )
1128 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1129
1130 m_calculatedMinSize = wxSize( width, height );
1131 return m_calculatedMinSize;
1132 }
1133
1134 void wxFlexGridSizer::AdjustForFlexDirection()
1135 {
1136 // the logic in CalcMin works when we resize flexibly in both directions
1137 // but maybe this is not the case
1138 if ( m_flexDirection != wxBOTH )
1139 {
1140 // select the array corresponding to the direction in which we do *not*
1141 // resize flexibly
1142 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1143 : m_rowHeights;
1144
1145 const int count = array.GetCount();
1146
1147 // find the largest value in this array
1148 int n, largest = 0;
1149 for ( n = 0; n < count; ++n )
1150 {
1151 if ( array[n] > largest )
1152 largest = array[n];
1153 }
1154
1155 // and now fill it with the largest value
1156 for ( n = 0; n < count; ++n )
1157 {
1158 array[n] = largest;
1159 }
1160 }
1161 }
1162
1163
1164 void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1165 int nrows, int ncols)
1166 {
1167 // what to do with the rows? by default, resize them proportionally
1168 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1169 {
1170 int sum_proportions = 0;
1171 int growable_space = 0;
1172 int num = 0;
1173 size_t idx;
1174 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1175 {
1176 // Since the number of rows/columns can change as items are
1177 // inserted/deleted, we need to verify at runtime that the
1178 // requested growable rows/columns are still valid.
1179 if (m_growableRows[idx] >= nrows)
1180 continue;
1181
1182 // If all items in a row/column are hidden, that row/column will
1183 // have a dimension of -1. This causes the row/column to be
1184 // hidden completely.
1185 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1186 continue;
1187 sum_proportions += m_growableRowsProportions[idx];
1188 growable_space += m_rowHeights[ m_growableRows[idx] ];
1189 num++;
1190 }
1191
1192 if (num > 0)
1193 {
1194 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1195 {
1196 if (m_growableRows[idx] >= nrows )
1197 continue;
1198 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1199 m_rowHeights[ m_growableRows[idx] ] = 0;
1200 else
1201 {
1202 int delta = (sz.y - minsz.y);
1203 if (sum_proportions == 0)
1204 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1205 else
1206 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1207 m_rowHeights[ m_growableRows[idx] ] = delta;
1208 }
1209 }
1210 }
1211 }
1212 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1213 {
1214 // rounding problem?
1215 for ( int row = 0; row < nrows; ++row )
1216 m_rowHeights[ row ] = sz.y / nrows;
1217 }
1218
1219 // the same logic as above but for the columns
1220 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1221 {
1222 int sum_proportions = 0;
1223 int growable_space = 0;
1224 int num = 0;
1225 size_t idx;
1226 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1227 {
1228 // Since the number of rows/columns can change as items are
1229 // inserted/deleted, we need to verify at runtime that the
1230 // requested growable rows/columns are still valid.
1231 if (m_growableCols[idx] >= ncols)
1232 continue;
1233
1234 // If all items in a row/column are hidden, that row/column will
1235 // have a dimension of -1. This causes the column to be hidden
1236 // completely.
1237 if (m_colWidths[ m_growableCols[idx] ] == -1)
1238 continue;
1239 sum_proportions += m_growableColsProportions[idx];
1240 growable_space += m_colWidths[ m_growableCols[idx] ];
1241 num++;
1242 }
1243
1244 if (num > 0)
1245 {
1246 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1247 {
1248 if (m_growableCols[idx] >= ncols )
1249 continue;
1250 if (m_colWidths[ m_growableCols[idx] ] == -1)
1251 m_colWidths[ m_growableCols[idx] ] = 0;
1252 else
1253 {
1254 int delta = (sz.x - minsz.x);
1255 if (sum_proportions == 0)
1256 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1257 else
1258 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1259 m_colWidths[ m_growableCols[idx] ] = delta;
1260 }
1261 }
1262 }
1263 }
1264 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1265 {
1266 for ( int col=0; col < ncols; ++col )
1267 m_colWidths[ col ] = sz.x / ncols;
1268 }
1269 }
1270
1271
1272 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1273 {
1274 m_growableRows.Add( idx );
1275 m_growableRowsProportions.Add( proportion );
1276 }
1277
1278 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1279 {
1280 m_growableRows.Remove( idx );
1281 }
1282
1283 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1284 {
1285 m_growableCols.Add( idx );
1286 m_growableColsProportions.Add( proportion );
1287 }
1288
1289 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1290 {
1291 m_growableCols.Remove( idx );
1292 }
1293
1294 //---------------------------------------------------------------------------
1295 // wxBoxSizer
1296 //---------------------------------------------------------------------------
1297
1298 wxBoxSizer::wxBoxSizer( int orient )
1299 : m_orient( orient )
1300 {
1301 }
1302
1303 void wxBoxSizer::RecalcSizes()
1304 {
1305 if (m_children.GetCount() == 0)
1306 return;
1307
1308 int delta = 0;
1309 if (m_stretchable)
1310 {
1311 if (m_orient == wxHORIZONTAL)
1312 delta = m_size.x - m_fixedWidth;
1313 else
1314 delta = m_size.y - m_fixedHeight;
1315 }
1316
1317 wxPoint pt( m_position );
1318
1319 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1320 while (node)
1321 {
1322 wxSizerItem *item = node->GetData();
1323
1324 if (item->IsShown())
1325 {
1326 wxSize size( item->GetMinSizeWithBorder() );
1327
1328 if (m_orient == wxVERTICAL)
1329 {
1330 wxCoord height = size.y;
1331 if (item->GetProportion())
1332 {
1333 // Because of at least one visible item has non-zero
1334 // proportion then m_stretchable is not zero
1335 height = (delta * item->GetProportion()) / m_stretchable;
1336 }
1337
1338 wxPoint child_pos( pt );
1339 wxSize child_size( wxSize( size.x, height) );
1340
1341 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1342 child_size.x = m_size.x;
1343 else if (item->GetFlag() & wxALIGN_RIGHT)
1344 child_pos.x += m_size.x - size.x;
1345 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1346 // XXX wxCENTER is added for backward compatibility;
1347 // wxALIGN_CENTER should be used in new code
1348 child_pos.x += (m_size.x - size.x) / 2;
1349
1350 item->SetDimension( child_pos, child_size );
1351
1352 pt.y += height;
1353 }
1354 else
1355 {
1356 wxCoord width = size.x;
1357 if (item->GetProportion())
1358 {
1359 // Because of at least one visible item has non-zero
1360 // proportion then m_stretchable is not zero
1361 width = (delta * item->GetProportion()) / m_stretchable;
1362 }
1363
1364 wxPoint child_pos( pt );
1365 wxSize child_size( wxSize(width, size.y) );
1366
1367 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1368 child_size.y = m_size.y;
1369 else if (item->GetFlag() & wxALIGN_BOTTOM)
1370 child_pos.y += m_size.y - size.y;
1371 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1372 // XXX wxCENTER is added for backward compatibility;
1373 // wxALIGN_CENTER should be used in new code
1374 child_pos.y += (m_size.y - size.y) / 2;
1375
1376 item->SetDimension( child_pos, child_size );
1377
1378 pt.x += width;
1379 }
1380 }
1381
1382 node = node->GetNext();
1383 }
1384 }
1385
1386 wxSize wxBoxSizer::CalcMin()
1387 {
1388 if (m_children.GetCount() == 0)
1389 return wxSize(10,10);
1390
1391 m_stretchable = 0;
1392 m_minWidth = 0;
1393 m_minHeight = 0;
1394 m_fixedWidth = 0;
1395 m_fixedHeight = 0;
1396
1397 // precalc item minsizes and count proportions
1398 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1399 while (node)
1400 {
1401 wxSizerItem *item = node->GetData();
1402
1403 if (item->IsShown())
1404 item->CalcMin(); // result is stored in the item
1405
1406 if (item->IsShown() && item->GetProportion() != 0)
1407 m_stretchable += item->GetProportion();
1408
1409 node = node->GetNext();
1410 }
1411
1412 // Total minimum size (width or height) of sizer
1413 int maxMinSize = 0;
1414
1415 node = m_children.GetFirst();
1416 while (node)
1417 {
1418 wxSizerItem *item = node->GetData();
1419
1420 if (item->IsShown() && item->GetProportion() != 0)
1421 {
1422 int stretch = item->GetProportion();
1423 wxSize size( item->GetMinSizeWithBorder() );
1424 int minSize;
1425
1426 // Integer division rounded up is (a + b - 1) / b
1427 // Round up needed in order to guarantee that all
1428 // all items will have size not less then their min size
1429 if (m_orient == wxHORIZONTAL)
1430 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1431 else
1432 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1433
1434 if (minSize > maxMinSize)
1435 maxMinSize = minSize;
1436 }
1437 node = node->GetNext();
1438 }
1439
1440 // Calculate overall minimum size
1441 node = m_children.GetFirst();
1442 while (node)
1443 {
1444 wxSizerItem *item = node->GetData();
1445
1446 if (item->IsShown())
1447 {
1448 wxSize size( item->GetMinSizeWithBorder() );
1449 if (item->GetProportion() != 0)
1450 {
1451 if (m_orient == wxHORIZONTAL)
1452 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1453 else
1454 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1455 }
1456 else
1457 {
1458 if (m_orient == wxVERTICAL)
1459 {
1460 m_fixedHeight += size.y;
1461 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1462 }
1463 else
1464 {
1465 m_fixedWidth += size.x;
1466 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1467 }
1468 }
1469
1470 if (m_orient == wxHORIZONTAL)
1471 {
1472 m_minWidth += size.x;
1473 m_minHeight = wxMax( m_minHeight, size.y );
1474 }
1475 else
1476 {
1477 m_minHeight += size.y;
1478 m_minWidth = wxMax( m_minWidth, size.x );
1479 }
1480 }
1481 node = node->GetNext();
1482 }
1483
1484 return wxSize( m_minWidth, m_minHeight );
1485 }
1486
1487 //---------------------------------------------------------------------------
1488 // wxStaticBoxSizer
1489 //---------------------------------------------------------------------------
1490
1491 #if wxUSE_STATBOX
1492
1493 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1494 : wxBoxSizer( orient )
1495 , m_staticBox( box )
1496 {
1497 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1498 }
1499
1500 static void GetStaticBoxBorders( wxStaticBox *box,
1501 int *borderTop,
1502 int *borderOther)
1503 {
1504 // this has to be done platform by platform as there is no way to
1505 // guess the thickness of a wxStaticBox border
1506 #ifdef __WXCOCOA__
1507 box->GetBordersForSizer(borderTop,borderOther);
1508 #elif defined(__WXMAC__)
1509
1510 static int extraTop = -1; // Uninitted
1511 static int other = 5;
1512
1513 if ( extraTop == -1 )
1514 {
1515 // The minimal border used for the top. Later on the staticbox'
1516 // font height is added to this.
1517 extraTop = 0;
1518
1519 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1520 {
1521 // As indicated by the HIG, Panther needs an extra border of 11
1522 // pixels (otherwise overlapping occurs at the top). The "other"
1523 // border has to be 11.
1524 extraTop = 11;
1525 other = 11;
1526 }
1527
1528 }
1529
1530 *borderTop = extraTop + box->GetCharHeight();
1531 *borderOther = other;
1532
1533 #else
1534 #ifdef __WXGTK__
1535 if ( box->GetLabel().IsEmpty() )
1536 *borderTop = 5;
1537 else
1538 #endif // __WXGTK__
1539 *borderTop = box->GetCharHeight();
1540
1541 *borderOther = 5;
1542 #endif // __WXCOCOA__
1543 }
1544
1545 void wxStaticBoxSizer::RecalcSizes()
1546 {
1547 int top_border, other_border;
1548 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1549
1550 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1551
1552 wxPoint old_pos( m_position );
1553 m_position.x += other_border;
1554 m_position.y += top_border;
1555 wxSize old_size( m_size );
1556 m_size.x -= 2*other_border;
1557 m_size.y -= top_border + other_border;
1558
1559 wxBoxSizer::RecalcSizes();
1560
1561 m_position = old_pos;
1562 m_size = old_size;
1563 }
1564
1565 wxSize wxStaticBoxSizer::CalcMin()
1566 {
1567 int top_border, other_border;
1568 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1569
1570 wxSize ret( wxBoxSizer::CalcMin() );
1571 ret.x += 2*other_border;
1572 ret.y += other_border + top_border;
1573
1574 return ret;
1575 }
1576
1577 void wxStaticBoxSizer::ShowItems( bool show )
1578 {
1579 m_staticBox->Show( show );
1580 wxBoxSizer::ShowItems( show );
1581 }
1582
1583 #endif // wxUSE_STATBOX
1584
1585
1586 #if WXWIN_COMPATIBILITY_2_4
1587
1588 // ----------------------------------------------------------------------------
1589 // wxNotebookSizer
1590 // ----------------------------------------------------------------------------
1591
1592 #if wxUSE_BOOKCTRL
1593 IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1594 #if wxUSE_NOTEBOOK
1595 IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1596 #endif // wxUSE_NOTEBOOK
1597 #endif // wxUSE_BOOKCTRL
1598
1599 #if wxUSE_BOOKCTRL
1600
1601 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1602 : m_bookctrl(bookctrl)
1603 {
1604 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1605 }
1606
1607 void wxBookCtrlSizer::RecalcSizes()
1608 {
1609 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1610 }
1611
1612 wxSize wxBookCtrlSizer::CalcMin()
1613 {
1614 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1615
1616 sizeBorder.x += 5;
1617 sizeBorder.y += 5;
1618
1619 if ( m_bookctrl->GetPageCount() == 0 )
1620 {
1621 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1622 }
1623
1624 int maxX = 0;
1625 int maxY = 0;
1626
1627 wxWindowList::compatibility_iterator
1628 node = m_bookctrl->GetChildren().GetFirst();
1629 while (node)
1630 {
1631 wxWindow *item = node->GetData();
1632 wxSizer *itemsizer = item->GetSizer();
1633
1634 if (itemsizer)
1635 {
1636 wxSize subsize( itemsizer->CalcMin() );
1637
1638 if (subsize.x > maxX)
1639 maxX = subsize.x;
1640 if (subsize.y > maxY)
1641 maxY = subsize.y;
1642 }
1643
1644 node = node->GetNext();
1645 }
1646
1647 return wxSize( maxX, maxY ) + sizeBorder;
1648 }
1649
1650 #if wxUSE_NOTEBOOK
1651
1652 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1653 {
1654 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1655 m_bookctrl = nb;
1656 }
1657
1658 #endif // wxUSE_NOTEBOOOK
1659 #endif // wxUSE_BOOKCTRL
1660
1661 #endif // WXWIN_COMPATIBILITY_2_4