]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
call wxApp::OnUnhandledException()
[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 }
918
919 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
920 : m_rows( 0 )
921 , m_cols( cols )
922 , m_vgap( vgap )
923 , m_hgap( hgap )
924 {
925 }
926
927 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
928 {
929 int nitems = m_children.GetCount();
930 if ( nitems)
931 {
932 if ( m_cols )
933 {
934 ncols = m_cols;
935 nrows = (nitems + m_cols - 1) / m_cols;
936 }
937 else if ( m_rows )
938 {
939 ncols = (nitems + m_rows - 1) / m_rows;
940 nrows = m_rows;
941 }
942 else // 0 columns, 0 rows?
943 {
944 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
945
946 nrows = ncols = 0;
947 }
948 }
949
950 return nitems;
951 }
952
953 void wxGridSizer::RecalcSizes()
954 {
955 int nitems, nrows, ncols;
956 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
957 return;
958
959 wxSize sz( GetSize() );
960 wxPoint pt( GetPosition() );
961
962 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
963 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
964
965 int x = pt.x;
966 for (int c = 0; c < ncols; c++)
967 {
968 int y = pt.y;
969 for (int r = 0; r < nrows; r++)
970 {
971 int i = r * ncols + c;
972 if (i < nitems)
973 {
974 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
975
976 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
977
978 SetItemBounds( node->GetData(), x, y, w, h);
979 }
980 y = y + h + m_vgap;
981 }
982 x = x + w + m_hgap;
983 }
984 }
985
986 wxSize wxGridSizer::CalcMin()
987 {
988 int nrows, ncols;
989 if ( CalcRowsCols(nrows, ncols) == 0 )
990 return wxSize(10, 10);
991
992 // Find the max width and height for any component
993 int w = 0;
994 int h = 0;
995
996 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
997 while (node)
998 {
999 wxSizerItem *item = node->GetData();
1000 wxSize sz( item->CalcMin() );
1001
1002 w = wxMax( w, sz.x );
1003 h = wxMax( h, sz.y );
1004
1005 node = node->GetNext();
1006 }
1007
1008 return wxSize( ncols * w + (ncols-1) * m_hgap,
1009 nrows * h + (nrows-1) * m_vgap );
1010 }
1011
1012 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1013 {
1014 wxPoint pt( x,y );
1015 wxSize sz( item->CalcMin() );
1016 int flag = item->GetFlag();
1017
1018 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1019 {
1020 sz = wxSize(w, h);
1021 }
1022 else
1023 {
1024 if (flag & wxALIGN_CENTER_HORIZONTAL)
1025 {
1026 pt.x = x + (w - sz.x) / 2;
1027 }
1028 else if (flag & wxALIGN_RIGHT)
1029 {
1030 pt.x = x + (w - sz.x);
1031 }
1032
1033 if (flag & wxALIGN_CENTER_VERTICAL)
1034 {
1035 pt.y = y + (h - sz.y) / 2;
1036 }
1037 else if (flag & wxALIGN_BOTTOM)
1038 {
1039 pt.y = y + (h - sz.y);
1040 }
1041 }
1042
1043 item->SetDimension(pt, sz);
1044 }
1045
1046 //---------------------------------------------------------------------------
1047 // wxFlexGridSizer
1048 //---------------------------------------------------------------------------
1049
1050 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1051 : wxGridSizer( rows, cols, vgap, hgap ),
1052 m_flexDirection(wxBOTH),
1053 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1054 {
1055 }
1056
1057 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1058 : wxGridSizer( cols, vgap, hgap ),
1059 m_flexDirection(wxBOTH),
1060 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1061 {
1062 }
1063
1064 wxFlexGridSizer::~wxFlexGridSizer()
1065 {
1066 }
1067
1068 void wxFlexGridSizer::RecalcSizes()
1069 {
1070 int nitems, nrows, ncols;
1071 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1072 return;
1073
1074 wxSize sz( GetSize() );
1075 wxSize minsz( CalcMin() );
1076 wxPoint pt( GetPosition() );
1077
1078 // what to do with the rows? by default, resize them proportionally
1079 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1080 {
1081 int sum_proportions = 0;
1082 int growable_space = 0;
1083 int num = 0;
1084 size_t idx;
1085 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1086 {
1087 // Since the number of rows/columns can change as items are inserted/deleted, we need
1088 // to verify at runtime that the requested growable rows/columns are still valid.
1089 if (m_growableRows[idx] >= nrows)
1090 continue;
1091 // If all items in a row/column are hidden, that row/column will have a dimension of -1.
1092 // This causes the row/column to be hidden completely.
1093 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1094 continue;
1095 sum_proportions += m_growableRowsProportions[idx];
1096 growable_space += m_rowHeights[ m_growableRows[idx] ];
1097 num++;
1098 }
1099
1100 if (num > 0)
1101 {
1102 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1103 {
1104 if (m_growableRows[idx] >= nrows )
1105 continue;
1106 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1107 m_rowHeights[ m_growableRows[idx] ] = 0;
1108 else
1109 {
1110 int delta = (sz.y - minsz.y);
1111 if (sum_proportions == 0)
1112 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1113 else
1114 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1115 m_rowHeights[ m_growableRows[idx] ] = delta;
1116 }
1117 }
1118 }
1119 }
1120 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1121 {
1122 // rounding problem?
1123 for ( int row = 0; row < nrows; ++row )
1124 m_rowHeights[ row ] = sz.y / nrows;
1125 }
1126
1127 // the same logic as above but for the columns
1128 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1129 {
1130 int sum_proportions = 0;
1131 int growable_space = 0;
1132 int num = 0;
1133 size_t idx;
1134 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1135 {
1136 // Since the number of rows/columns can change as items are inserted/deleted, we need
1137 // to verify at runtime that the requested growable rows/columns are still valid.
1138 if (m_growableCols[idx] >= ncols)
1139 continue;
1140 // If all items in a row/column are hidden, that row/column will have a dimension of -1.
1141 // This causes the column to be hidden completely.
1142 if (m_colWidths[ m_growableCols[idx] ] == -1)
1143 continue;
1144 sum_proportions += m_growableColsProportions[idx];
1145 // wtb 5/12/02 bugfix - was m_ColWidths[idx]!!
1146 growable_space += m_colWidths[ m_growableCols[idx] ];
1147 num++;
1148 }
1149
1150 if (num > 0)
1151 {
1152 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1153 {
1154 if (m_growableCols[idx] >= ncols )
1155 continue;
1156 if (m_colWidths[ m_growableCols[idx] ] == -1)
1157 m_colWidths[ m_growableCols[idx] ] = 0;
1158 else
1159 {
1160 int delta = (sz.x - minsz.x);
1161 if (sum_proportions == 0)
1162 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1163 else
1164 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1165 m_colWidths[ m_growableCols[idx] ] = delta;
1166 }
1167 }
1168 }
1169 }
1170 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1171 {
1172 for ( int col=0; col < ncols; ++col )
1173 m_colWidths[ col ] = sz.x / ncols;
1174 }
1175
1176 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1177
1178 int x = pt.x;
1179 for (int c = 0; c < ncols; c++)
1180 {
1181 int y = pt.y;
1182 for (int r = 0; r < nrows; r++)
1183 {
1184 int i = r * ncols + c;
1185 if (i < nitems)
1186 {
1187 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1188
1189 wxASSERT_MSG( node, _T("Failed to find node") );
1190
1191 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1192 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1193
1194 SetItemBounds( node->GetData(), x, y, w, h);
1195 }
1196 y = y + m_rowHeights[r] + m_vgap;
1197 }
1198 x = x + m_colWidths[c] + m_hgap;
1199 }
1200 }
1201
1202 wxSize wxFlexGridSizer::CalcMin()
1203 {
1204 int nrows,
1205 ncols;
1206 size_t i, s;
1207
1208 // Number of rows/columns can change as items are added or removed.
1209 if ( !CalcRowsCols(nrows, ncols) )
1210 return wxSize(10, 10);
1211
1212 m_rowHeights.SetCount(nrows);
1213 m_colWidths.SetCount(ncols);
1214
1215 // We have to recalcuate the sizes in case an item has wxADJUST_MINSIZE, has changed
1216 // minimum size since the previous layout, or has been hidden using wxSizer::Show().
1217 // If all the items in a row/column are hidden, the final dimension of the row/column
1218 // will be -1, indicating that the column itself is hidden.
1219 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1220 m_rowHeights[ i ] = -1;
1221 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1222 m_colWidths[ i ] = -1;
1223
1224 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1225
1226 i = 0;
1227 while (node)
1228 {
1229 wxSizerItem *item = node->GetData();
1230 if ( item->IsShown() )
1231 {
1232 wxSize sz( item->CalcMin() );
1233 int row = i / ncols;
1234 int col = i % ncols;
1235
1236 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1237 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1238 }
1239
1240 node = node->GetNext();
1241 i++;
1242 }
1243
1244 // the logic above works when we resize flexibly in both directions but
1245 // maybe this is not the case
1246 if ( m_flexDirection != wxBOTH )
1247 {
1248 // select the array corresponding to the direction in which we do *not*
1249 // resize flexibly
1250 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1251 : m_rowHeights;
1252
1253 const int count = array.GetCount();
1254
1255 // find the largest value in this array
1256 int n, largest = 0;
1257 for ( n = 0; n < count; ++n )
1258 {
1259 if ( array[n] > largest )
1260 largest = array[n];
1261 }
1262
1263 // and now fill it with the largest value
1264 for ( n = 0; n < count; ++n )
1265 {
1266 array[n] = largest;
1267 }
1268 }
1269
1270 // Sum total minimum size, including gaps between rows/columns.
1271 // -1 is used as a magic number meaning empty column.
1272 int width = 0;
1273 for (int col = 0; col < ncols; col++)
1274 if ( m_colWidths[ col ] != -1 )
1275 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1276
1277 int height = 0;
1278 for (int row = 0; row < nrows; row++)
1279 if ( m_rowHeights[ row ] != -1 )
1280 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1281
1282 return wxSize( width, height );
1283 }
1284
1285 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1286 {
1287 m_growableRows.Add( idx );
1288 m_growableRowsProportions.Add( proportion );
1289 }
1290
1291 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1292 {
1293 m_growableRows.Remove( idx );
1294 }
1295
1296 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1297 {
1298 m_growableCols.Add( idx );
1299 m_growableColsProportions.Add( proportion );
1300 }
1301
1302 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1303 {
1304 m_growableCols.Remove( idx );
1305 }
1306
1307 //---------------------------------------------------------------------------
1308 // wxBoxSizer
1309 //---------------------------------------------------------------------------
1310
1311 wxBoxSizer::wxBoxSizer( int orient )
1312 : m_orient( orient )
1313 {
1314 }
1315
1316 void wxBoxSizer::RecalcSizes()
1317 {
1318 if (m_children.GetCount() == 0)
1319 return;
1320
1321 int delta = 0;
1322 if (m_stretchable)
1323 {
1324 if (m_orient == wxHORIZONTAL)
1325 delta = m_size.x - m_fixedWidth;
1326 else
1327 delta = m_size.y - m_fixedHeight;
1328 }
1329
1330 wxPoint pt( m_position );
1331
1332 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1333 while (node)
1334 {
1335 wxSizerItem *item = node->GetData();
1336
1337 if (item->IsShown())
1338 {
1339 wxSize size( item->CalcMin() );
1340
1341 if (m_orient == wxVERTICAL)
1342 {
1343 wxCoord height = size.y;
1344 if (item->GetProportion())
1345 {
1346 // Because of at least one visible item has non-zero
1347 // proportion then m_stretchable is not zero
1348 height = (delta * item->GetProportion()) / m_stretchable;
1349 }
1350
1351 wxPoint child_pos( pt );
1352 wxSize child_size( wxSize( size.x, height) );
1353
1354 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1355 child_size.x = m_size.x;
1356 else if (item->GetFlag() & wxALIGN_RIGHT)
1357 child_pos.x += m_size.x - size.x;
1358 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1359 // XXX wxCENTER is added for backward compatibility;
1360 // wxALIGN_CENTER should be used in new code
1361 child_pos.x += (m_size.x - size.x) / 2;
1362
1363 item->SetDimension( child_pos, child_size );
1364
1365 pt.y += height;
1366 }
1367 else
1368 {
1369 wxCoord width = size.x;
1370 if (item->GetProportion())
1371 {
1372 // Because of at least one visible item has non-zero
1373 // proportion then m_stretchable is not zero
1374 width = (delta * item->GetProportion()) / m_stretchable;
1375 }
1376
1377 wxPoint child_pos( pt );
1378 wxSize child_size( wxSize(width, size.y) );
1379
1380 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1381 child_size.y = m_size.y;
1382 else if (item->GetFlag() & wxALIGN_BOTTOM)
1383 child_pos.y += m_size.y - size.y;
1384 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1385 // XXX wxCENTER is added for backward compatibility;
1386 // wxALIGN_CENTER should be used in new code
1387 child_pos.y += (m_size.y - size.y) / 2;
1388
1389 item->SetDimension( child_pos, child_size );
1390
1391 pt.x += width;
1392 }
1393 }
1394
1395 node = node->GetNext();
1396 }
1397 }
1398
1399 wxSize wxBoxSizer::CalcMin()
1400 {
1401 if (m_children.GetCount() == 0)
1402 return wxSize(10,10);
1403
1404 m_stretchable = 0;
1405 m_minWidth = 0;
1406 m_minHeight = 0;
1407 m_fixedWidth = 0;
1408 m_fixedHeight = 0;
1409
1410 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1411 while (node)
1412 {
1413 wxSizerItem *item = node->GetData();
1414
1415 if (item->IsShown() && item->GetProportion() != 0)
1416 m_stretchable += item->GetProportion();
1417
1418 node = node->GetNext();
1419 }
1420
1421 // Total minimum size (width or height) of sizer
1422 int maxMinSize = 0;
1423
1424 node = m_children.GetFirst();
1425 while (node)
1426 {
1427 wxSizerItem *item = node->GetData();
1428
1429 if (item->IsShown() && item->GetProportion() != 0)
1430 {
1431 int stretch = item->GetProportion();
1432 wxSize size( item->CalcMin() );
1433 int minSize;
1434
1435 // Integer division rounded up is (a + b - 1) / b
1436 // Round up needed in order to guarantee that all
1437 // all items will have size not less then their min size
1438 if (m_orient == wxHORIZONTAL)
1439 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1440 else
1441 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1442
1443 if (minSize > maxMinSize)
1444 maxMinSize = minSize;
1445 }
1446 node = node->GetNext();
1447 }
1448
1449 // Calculate overall minimum size
1450 node = m_children.GetFirst();
1451 while (node)
1452 {
1453 wxSizerItem *item = node->GetData();
1454
1455 if (item->IsShown())
1456 {
1457 wxSize size( item->CalcMin() );
1458 if (item->GetProportion() != 0)
1459 {
1460 if (m_orient == wxHORIZONTAL)
1461 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1462 else
1463 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1464 }
1465 else
1466 {
1467 if (m_orient == wxVERTICAL)
1468 {
1469 m_fixedHeight += size.y;
1470 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1471 }
1472 else
1473 {
1474 m_fixedWidth += size.x;
1475 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1476 }
1477 }
1478
1479 if (m_orient == wxHORIZONTAL)
1480 {
1481 m_minWidth += size.x;
1482 m_minHeight = wxMax( m_minHeight, size.y );
1483 }
1484 else
1485 {
1486 m_minHeight += size.y;
1487 m_minWidth = wxMax( m_minWidth, size.x );
1488 }
1489 }
1490 node = node->GetNext();
1491 }
1492
1493 return wxSize( m_minWidth, m_minHeight );
1494 }
1495
1496 //---------------------------------------------------------------------------
1497 // wxStaticBoxSizer
1498 //---------------------------------------------------------------------------
1499
1500 #if wxUSE_STATBOX
1501
1502 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1503 : wxBoxSizer( orient )
1504 , m_staticBox( box )
1505 {
1506 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1507 }
1508
1509 static void GetStaticBoxBorders( wxStaticBox *box,
1510 int *borderTop,
1511 int *borderOther)
1512 {
1513 // this has to be done platform by platform as there is no way to
1514 // guess the thickness of a wxStaticBox border
1515 #ifdef __WXCOCOA__
1516 box->GetBordersForSizer(borderTop,borderOther);
1517 #else // __WXCOCOA__
1518 #ifdef __WXGTK__
1519 if ( box->GetLabel().IsEmpty() )
1520 *borderTop = 5;
1521 else
1522 #endif // __WXGTK__
1523 *borderTop = box->GetCharHeight();
1524
1525 *borderOther = 5;
1526 #endif // __WXCOCOA__
1527 }
1528
1529 void wxStaticBoxSizer::RecalcSizes()
1530 {
1531 int top_border, other_border;
1532 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1533
1534 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1535
1536 wxPoint old_pos( m_position );
1537 m_position.x += other_border;
1538 m_position.y += top_border;
1539 wxSize old_size( m_size );
1540 m_size.x -= 2*other_border;
1541 m_size.y -= top_border + other_border;
1542
1543 wxBoxSizer::RecalcSizes();
1544
1545 m_position = old_pos;
1546 m_size = old_size;
1547 }
1548
1549 wxSize wxStaticBoxSizer::CalcMin()
1550 {
1551 int top_border, other_border;
1552 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1553
1554 wxSize ret( wxBoxSizer::CalcMin() );
1555 ret.x += 2*other_border;
1556 ret.y += other_border + top_border;
1557
1558 return ret;
1559 }
1560
1561 #endif // wxUSE_STATBOX
1562
1563 // ----------------------------------------------------------------------------
1564 // wxNotebookSizer
1565 // ----------------------------------------------------------------------------
1566
1567 #if wxUSE_BOOKCTRL
1568
1569 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1570 : m_bookctrl(bookctrl)
1571 {
1572 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1573 }
1574
1575 void wxBookCtrlSizer::RecalcSizes()
1576 {
1577 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1578 }
1579
1580 wxSize wxBookCtrlSizer::CalcMin()
1581 {
1582 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1583
1584 sizeBorder.x += 5;
1585 sizeBorder.y += 5;
1586
1587 if ( m_bookctrl->GetPageCount() == 0 )
1588 {
1589 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1590 }
1591
1592 int maxX = 0;
1593 int maxY = 0;
1594
1595 wxWindowList::compatibility_iterator
1596 node = m_bookctrl->GetChildren().GetFirst();
1597 while (node)
1598 {
1599 wxWindow *item = node->GetData();
1600 wxSizer *itemsizer = item->GetSizer();
1601
1602 if (itemsizer)
1603 {
1604 wxSize subsize( itemsizer->CalcMin() );
1605
1606 if (subsize.x > maxX)
1607 maxX = subsize.x;
1608 if (subsize.y > maxY)
1609 maxY = subsize.y;
1610 }
1611
1612 node = node->GetNext();
1613 }
1614
1615 return wxSize( maxX, maxY ) + sizeBorder;
1616 }
1617
1618
1619 #if wxUSE_NOTEBOOK
1620
1621 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1622 : wxBookCtrlSizer(nb)
1623 {
1624 }
1625
1626 #endif // wxUSE_NOTEBOOOK
1627 #endif // wxUSE_BOOKCTRL
1628