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