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