]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
2950163aee77e5454abe200f479b687fdf39c147
[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;
567 if (window->IsTopLevel())
568 size = FitSize( window );
569 else
570 size = GetMinWindowSize( window );
571
572 window->SetSize( size );
573
574 return size;
575 }
576
577 void wxSizer::FitInside( wxWindow *window )
578 {
579 wxSize size;
580 if (window->IsTopLevel())
581 size = VirtualFitSize( window );
582 else
583 size = GetMinClientSize( window );
584
585 window->SetVirtualSize( size );
586 }
587
588 void wxSizer::Layout()
589 {
590 CalcMin();
591 RecalcSizes();
592 }
593
594 void wxSizer::SetSizeHints( wxWindow *window )
595 {
596 // Preserve the window's max size hints, but set the
597 // lower bound according to the sizer calculations.
598
599 wxSize size = Fit( window );
600
601 window->SetSizeHints( size.x,
602 size.y,
603 window->GetMaxWidth(),
604 window->GetMaxHeight() );
605 }
606
607 void wxSizer::SetVirtualSizeHints( wxWindow *window )
608 {
609 // Preserve the window's max size hints, but set the
610 // lower bound according to the sizer calculations.
611
612 FitInside( window );
613 wxSize size( window->GetVirtualSize() );
614 window->SetVirtualSizeHints( size.x,
615 size.y,
616 window->GetMaxWidth(),
617 window->GetMaxHeight() );
618 }
619
620 wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
621 {
622 return window->GetMaxSize();
623 }
624
625 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
626 {
627 wxSize minSize( GetMinSize() );
628 wxSize size( window->GetSize() );
629 wxSize client_size( window->GetClientSize() );
630
631 return wxSize( minSize.x+size.x-client_size.x,
632 minSize.y+size.y-client_size.y );
633 }
634
635 // Return a window size that will fit within the screens dimensions
636 wxSize wxSizer::FitSize( wxWindow *window )
637 {
638 wxSize size = GetMinWindowSize( window );
639 wxSize sizeMax = GetMaxWindowSize( window );
640
641 // Limit the size if sizeMax != wxDefaultSize
642
643 if ( size.x > sizeMax.x && sizeMax.x != -1 )
644 size.x = sizeMax.x;
645 if ( size.y > sizeMax.y && sizeMax.y != -1 )
646 size.y = sizeMax.y;
647
648 return size;
649 }
650
651 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
652 {
653 wxSize maxSize( window->GetMaxSize() );
654
655 if( maxSize != wxDefaultSize )
656 {
657 wxSize size( window->GetSize() );
658 wxSize client_size( window->GetClientSize() );
659
660 return wxSize( maxSize.x + client_size.x - size.x,
661 maxSize.y + client_size.y - size.y );
662 }
663 else
664 return wxDefaultSize;
665 }
666
667 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
668 {
669 return GetMinSize(); // Already returns client size.
670 }
671
672 wxSize wxSizer::VirtualFitSize( wxWindow *window )
673 {
674 wxSize size = GetMinClientSize( window );
675 wxSize sizeMax = GetMaxClientSize( window );
676
677 // Limit the size if sizeMax != wxDefaultSize
678
679 if ( size.x > sizeMax.x && sizeMax.x != -1 )
680 size.x = sizeMax.x;
681 if ( size.y > sizeMax.y && sizeMax.y != -1 )
682 size.y = sizeMax.y;
683
684 return size;
685 }
686
687 void wxSizer::SetDimension( int x, int y, int width, int height )
688 {
689 m_position.x = x;
690 m_position.y = y;
691 m_size.x = width;
692 m_size.y = height;
693 Layout();
694 }
695
696 wxSize wxSizer::GetMinSize()
697 {
698 wxSize ret( CalcMin() );
699 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
700 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
701 return ret;
702 }
703
704 void wxSizer::DoSetMinSize( int width, int height )
705 {
706 m_minSize.x = width;
707 m_minSize.y = height;
708 }
709
710 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
711 {
712 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
713
714 // Is it our immediate child?
715
716 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
717 while (node)
718 {
719 wxSizerItem *item = node->GetData();
720
721 if (item->GetWindow() == window)
722 {
723 item->SetInitSize( width, height );
724 return true;
725 }
726 node = node->GetNext();
727 }
728
729 // No? Search any subsizers we own then
730
731 node = m_children.GetFirst();
732 while (node)
733 {
734 wxSizerItem *item = node->GetData();
735
736 if ( item->GetSizer() &&
737 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
738 {
739 // A child sizer found the requested windw, exit.
740 return true;
741 }
742 node = node->GetNext();
743 }
744
745 return false;
746 }
747
748 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
749 {
750 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
751
752 // Is it our immediate child?
753
754 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
755 while (node)
756 {
757 wxSizerItem *item = node->GetData();
758
759 if (item->GetSizer() == sizer)
760 {
761 item->GetSizer()->DoSetMinSize( width, height );
762 return true;
763 }
764 node = node->GetNext();
765 }
766
767 // No? Search any subsizers we own then
768
769 node = m_children.GetFirst();
770 while (node)
771 {
772 wxSizerItem *item = node->GetData();
773
774 if ( item->GetSizer() &&
775 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
776 {
777 // A child found the requested sizer, exit.
778 return true;
779 }
780 node = node->GetNext();
781 }
782
783 return false;
784 }
785
786 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
787 {
788 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
789
790 wxCHECK_MSG( node, false, _T("Failed to find child node") );
791
792 wxSizerItem *item = node->GetData();
793
794 if (item->GetSizer())
795 {
796 // Sizers contains the minimal size in them, if not calculated ...
797 item->GetSizer()->DoSetMinSize( width, height );
798 }
799 else
800 {
801 // ... but the minimal size of spacers and windows in stored in them
802 item->SetInitSize( width, height );
803 }
804
805 return true;
806 }
807
808 void wxSizer::Show( wxWindow *window, bool show )
809 {
810 wxASSERT_MSG( window, _T("Show for NULL window") );
811
812 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
813 while (node)
814 {
815 wxSizerItem *item = node->GetData();
816
817 if (item->GetWindow() == window)
818 {
819 item->Show( show );
820 break;
821 }
822 node = node->GetNext();
823 }
824 }
825
826 void wxSizer::Show( wxSizer *sizer, bool show )
827 {
828 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
829
830 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
831 while (node)
832 {
833 wxSizerItem *item = node->GetData();
834
835 if (item->GetSizer() == sizer)
836 {
837 item->Show( show );
838 break;
839 }
840 node = node->GetNext();
841 }
842 }
843
844 void wxSizer::Show( size_t index, bool show )
845 {
846 wxCHECK_RET( index < m_children.GetCount(),
847 _T("Show index is out of range") );
848
849 m_children.Item( index )->GetData()->Show( show );
850 }
851
852 void wxSizer::ShowItems( bool show )
853 {
854 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
855 while (node)
856 {
857 node->GetData()->Show( show );
858 node = node->GetNext();
859 }
860 }
861
862 bool wxSizer::IsShown( wxWindow *window ) const
863 {
864 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
865 while (node)
866 {
867 wxSizerItem *item = node->GetData();
868
869 if (item->GetWindow() == window)
870 {
871 return item->IsShown();
872 }
873 node = node->GetNext();
874 }
875
876 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
877
878 return false;
879 }
880
881 bool wxSizer::IsShown( wxSizer *sizer ) const
882 {
883 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
884 while (node)
885 {
886 wxSizerItem *item = node->GetData();
887
888 if (item->GetSizer() == sizer)
889 {
890 return item->IsShown();
891 }
892 node = node->GetNext();
893 }
894
895 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
896
897 return false;
898 }
899
900 bool wxSizer::IsShown( size_t index ) const
901 {
902 wxCHECK_MSG( index < m_children.GetCount(),
903 false,
904 _T("IsShown index is out of range") );
905
906 return m_children.Item( index )->GetData()->IsShown();
907 }
908
909
910 //---------------------------------------------------------------------------
911 // wxGridSizer
912 //---------------------------------------------------------------------------
913
914 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
915 : m_rows( rows )
916 , m_cols( cols )
917 , m_vgap( vgap )
918 , m_hgap( hgap )
919 {
920 }
921
922 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
923 : m_rows( 0 )
924 , m_cols( cols )
925 , m_vgap( vgap )
926 , m_hgap( hgap )
927 {
928 }
929
930 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
931 {
932 int nitems = m_children.GetCount();
933 if ( nitems)
934 {
935 if ( m_cols )
936 {
937 ncols = m_cols;
938 nrows = (nitems + m_cols - 1) / m_cols;
939 }
940 else if ( m_rows )
941 {
942 ncols = (nitems + m_rows - 1) / m_rows;
943 nrows = m_rows;
944 }
945 else // 0 columns, 0 rows?
946 {
947 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
948
949 nrows = ncols = 0;
950 }
951 }
952
953 return nitems;
954 }
955
956 void wxGridSizer::RecalcSizes()
957 {
958 int nitems, nrows, ncols;
959 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
960 return;
961
962 wxSize sz( GetSize() );
963 wxPoint pt( GetPosition() );
964
965 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
966 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
967
968 int x = pt.x;
969 for (int c = 0; c < ncols; c++)
970 {
971 int y = pt.y;
972 for (int r = 0; r < nrows; r++)
973 {
974 int i = r * ncols + c;
975 if (i < nitems)
976 {
977 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
978
979 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
980
981 SetItemBounds( node->GetData(), x, y, w, h);
982 }
983 y = y + h + m_vgap;
984 }
985 x = x + w + m_hgap;
986 }
987 }
988
989 wxSize wxGridSizer::CalcMin()
990 {
991 int nrows, ncols;
992 if ( CalcRowsCols(nrows, ncols) == 0 )
993 return wxSize(10, 10);
994
995 // Find the max width and height for any component
996 int w = 0;
997 int h = 0;
998
999 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1000 while (node)
1001 {
1002 wxSizerItem *item = node->GetData();
1003 wxSize sz( item->CalcMin() );
1004
1005 w = wxMax( w, sz.x );
1006 h = wxMax( h, sz.y );
1007
1008 node = node->GetNext();
1009 }
1010
1011 return wxSize( ncols * w + (ncols-1) * m_hgap,
1012 nrows * h + (nrows-1) * m_vgap );
1013 }
1014
1015 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1016 {
1017 wxPoint pt( x,y );
1018 wxSize sz( item->CalcMin() );
1019 int flag = item->GetFlag();
1020
1021 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1022 {
1023 sz = wxSize(w, h);
1024 }
1025 else
1026 {
1027 if (flag & wxALIGN_CENTER_HORIZONTAL)
1028 {
1029 pt.x = x + (w - sz.x) / 2;
1030 }
1031 else if (flag & wxALIGN_RIGHT)
1032 {
1033 pt.x = x + (w - sz.x);
1034 }
1035
1036 if (flag & wxALIGN_CENTER_VERTICAL)
1037 {
1038 pt.y = y + (h - sz.y) / 2;
1039 }
1040 else if (flag & wxALIGN_BOTTOM)
1041 {
1042 pt.y = y + (h - sz.y);
1043 }
1044 }
1045
1046 item->SetDimension(pt, sz);
1047 }
1048
1049 //---------------------------------------------------------------------------
1050 // wxFlexGridSizer
1051 //---------------------------------------------------------------------------
1052
1053 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1054 : wxGridSizer( rows, cols, vgap, hgap ),
1055 m_flexDirection(wxBOTH),
1056 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1057 {
1058 }
1059
1060 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1061 : wxGridSizer( cols, vgap, hgap ),
1062 m_flexDirection(wxBOTH),
1063 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1064 {
1065 }
1066
1067 wxFlexGridSizer::~wxFlexGridSizer()
1068 {
1069 }
1070
1071 void wxFlexGridSizer::RecalcSizes()
1072 {
1073 int nitems, nrows, ncols;
1074 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1075 return;
1076
1077 wxSize sz( GetSize() );
1078 wxSize minsz( CalcMin() );
1079 wxPoint pt( GetPosition() );
1080
1081 // what to do with the rows? by default, resize them proportionally
1082 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1083 {
1084 int sum_proportions = 0;
1085 int growable_space = 0;
1086 int num = 0;
1087 size_t idx;
1088 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1089 {
1090 // Since the number of rows/columns can change as items are inserted/deleted, we need
1091 // to verify at runtime that the requested growable rows/columns are still valid.
1092 if (m_growableRows[idx] >= nrows)
1093 continue;
1094 // If all items in a row/column are hidden, that row/column will have a dimension of -1.
1095 // This causes the row/column to be hidden completely.
1096 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1097 continue;
1098 sum_proportions += m_growableRowsProportions[idx];
1099 growable_space += m_rowHeights[ m_growableRows[idx] ];
1100 num++;
1101 }
1102
1103 if (num > 0)
1104 {
1105 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1106 {
1107 if (m_growableRows[idx] >= nrows )
1108 continue;
1109 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1110 m_rowHeights[ m_growableRows[idx] ] = 0;
1111 else
1112 {
1113 int delta = (sz.y - minsz.y);
1114 if (sum_proportions == 0)
1115 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1116 else
1117 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1118 m_rowHeights[ m_growableRows[idx] ] = delta;
1119 }
1120 }
1121 }
1122 }
1123 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1124 {
1125 // rounding problem?
1126 for ( int row = 0; row < nrows; ++row )
1127 m_rowHeights[ row ] = sz.y / nrows;
1128 }
1129
1130 // the same logic as above but for the columns
1131 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1132 {
1133 int sum_proportions = 0;
1134 int growable_space = 0;
1135 int num = 0;
1136 size_t idx;
1137 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1138 {
1139 // Since the number of rows/columns can change as items are inserted/deleted, we need
1140 // to verify at runtime that the requested growable rows/columns are still valid.
1141 if (m_growableCols[idx] >= ncols)
1142 continue;
1143 // If all items in a row/column are hidden, that row/column will have a dimension of -1.
1144 // This causes the column to be hidden completely.
1145 if (m_colWidths[ m_growableCols[idx] ] == -1)
1146 continue;
1147 sum_proportions += m_growableColsProportions[idx];
1148 // wtb 5/12/02 bugfix - was m_ColWidths[idx]!!
1149 growable_space += m_colWidths[ m_growableCols[idx] ];
1150 num++;
1151 }
1152
1153 if (num > 0)
1154 {
1155 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1156 {
1157 if (m_growableCols[idx] >= ncols )
1158 continue;
1159 if (m_colWidths[ m_growableCols[idx] ] == -1)
1160 m_colWidths[ m_growableCols[idx] ] = 0;
1161 else
1162 {
1163 int delta = (sz.x - minsz.x);
1164 if (sum_proportions == 0)
1165 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1166 else
1167 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1168 m_colWidths[ m_growableCols[idx] ] = delta;
1169 }
1170 }
1171 }
1172 }
1173 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1174 {
1175 for ( int col=0; col < ncols; ++col )
1176 m_colWidths[ col ] = sz.x / ncols;
1177 }
1178
1179 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1180
1181 int x = pt.x;
1182 for (int c = 0; c < ncols; c++)
1183 {
1184 int y = pt.y;
1185 for (int r = 0; r < nrows; r++)
1186 {
1187 int i = r * ncols + c;
1188 if (i < nitems)
1189 {
1190 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1191
1192 wxASSERT_MSG( node, _T("Failed to find node") );
1193
1194 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1195 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1196
1197 SetItemBounds( node->GetData(), x, y, w, h);
1198 }
1199 y = y + m_rowHeights[r] + m_vgap;
1200 }
1201 x = x + m_colWidths[c] + m_hgap;
1202 }
1203 }
1204
1205 wxSize wxFlexGridSizer::CalcMin()
1206 {
1207 int nrows,
1208 ncols;
1209 size_t i, s;
1210
1211 // Number of rows/columns can change as items are added or removed.
1212 if ( !CalcRowsCols(nrows, ncols) )
1213 return wxSize(10, 10);
1214
1215 m_rowHeights.SetCount(nrows);
1216 m_colWidths.SetCount(ncols);
1217
1218 // We have to recalcuate the sizes in case an item has wxADJUST_MINSIZE, has changed
1219 // minimum size since the previous layout, or has been hidden using wxSizer::Show().
1220 // If all the items in a row/column are hidden, the final dimension of the row/column
1221 // will be -1, indicating that the column itself is hidden.
1222 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1223 m_rowHeights[ i ] = -1;
1224 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1225 m_colWidths[ i ] = -1;
1226
1227 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1228
1229 i = 0;
1230 while (node)
1231 {
1232 wxSizerItem *item = node->GetData();
1233 if ( item->IsShown() )
1234 {
1235 wxSize sz( item->CalcMin() );
1236 int row = i / ncols;
1237 int col = i % ncols;
1238
1239 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1240 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1241 }
1242
1243 node = node->GetNext();
1244 i++;
1245 }
1246
1247 // the logic above works when we resize flexibly in both directions but
1248 // maybe this is not the case
1249 if ( m_flexDirection != wxBOTH )
1250 {
1251 // select the array corresponding to the direction in which we do *not*
1252 // resize flexibly
1253 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1254 : m_rowHeights;
1255
1256 const int count = array.GetCount();
1257
1258 // find the largest value in this array
1259 int n, largest = 0;
1260 for ( n = 0; n < count; ++n )
1261 {
1262 if ( array[n] > largest )
1263 largest = array[n];
1264 }
1265
1266 // and now fill it with the largest value
1267 for ( n = 0; n < count; ++n )
1268 {
1269 array[n] = largest;
1270 }
1271 }
1272
1273 // Sum total minimum size, including gaps between rows/columns.
1274 // -1 is used as a magic number meaning empty column.
1275 int width = 0;
1276 for (int col = 0; col < ncols; col++)
1277 if ( m_colWidths[ col ] != -1 )
1278 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1279
1280 int height = 0;
1281 for (int row = 0; row < nrows; row++)
1282 if ( m_rowHeights[ row ] != -1 )
1283 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1284
1285 return wxSize( width, height );
1286 }
1287
1288 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1289 {
1290 m_growableRows.Add( idx );
1291 m_growableRowsProportions.Add( proportion );
1292 }
1293
1294 void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx) )
1295 {
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 WXUNUSED(idx) )
1305 {
1306 }
1307
1308 //---------------------------------------------------------------------------
1309 // wxBoxSizer
1310 //---------------------------------------------------------------------------
1311
1312 wxBoxSizer::wxBoxSizer( int orient )
1313 : m_orient( orient )
1314 {
1315 }
1316
1317 void wxBoxSizer::RecalcSizes()
1318 {
1319 if (m_children.GetCount() == 0)
1320 return;
1321
1322 int delta = 0;
1323 int extra = 0;
1324 if (m_stretchable)
1325 {
1326 if (m_orient == wxHORIZONTAL)
1327 {
1328 delta = (m_size.x - m_fixedWidth) / m_stretchable;
1329 extra = (m_size.x - m_fixedWidth) % m_stretchable;
1330 }
1331 else
1332 {
1333 delta = (m_size.y - m_fixedHeight) / m_stretchable;
1334 extra = (m_size.y - m_fixedHeight) % m_stretchable;
1335 }
1336 }
1337
1338 wxPoint pt( m_position );
1339
1340 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1341 while (node)
1342 {
1343 wxSizerItem *item = node->GetData();
1344
1345 if (item->IsShown())
1346 {
1347 int weight = 1;
1348 if (item->GetProportion())
1349 weight = item->GetProportion();
1350
1351 wxSize size( item->CalcMin() );
1352
1353 if (m_orient == wxVERTICAL)
1354 {
1355 wxCoord height = size.y;
1356 if (item->GetProportion())
1357 {
1358 height = (delta * weight) + extra;
1359 extra = 0; // only the first item will get the remainder as extra size
1360 }
1361
1362 wxPoint child_pos( pt );
1363 wxSize child_size( wxSize( size.x, height) );
1364
1365 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1366 child_size.x = m_size.x;
1367 else if (item->GetFlag() & wxALIGN_RIGHT)
1368 child_pos.x += m_size.x - size.x;
1369 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1370 // XXX wxCENTER is added for backward compatibility;
1371 // wxALIGN_CENTER should be used in new code
1372 child_pos.x += (m_size.x - size.x) / 2;
1373
1374 item->SetDimension( child_pos, child_size );
1375
1376 pt.y += height;
1377 }
1378 else
1379 {
1380 wxCoord width = size.x;
1381 if (item->GetProportion())
1382 {
1383 width = (delta * weight) + extra;
1384 extra = 0; // only the first item will get the remainder as extra size
1385 }
1386
1387 wxPoint child_pos( pt );
1388 wxSize child_size( wxSize(width, size.y) );
1389
1390 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1391 child_size.y = m_size.y;
1392 else if (item->GetFlag() & wxALIGN_BOTTOM)
1393 child_pos.y += m_size.y - size.y;
1394 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1395 // XXX wxCENTER is added for backward compatibility;
1396 // wxALIGN_CENTER should be used in new code
1397 child_pos.y += (m_size.y - size.y) / 2;
1398
1399 item->SetDimension( child_pos, child_size );
1400
1401 pt.x += width;
1402 }
1403 }
1404
1405 node = node->GetNext();
1406 }
1407 }
1408
1409 wxSize wxBoxSizer::CalcMin()
1410 {
1411 if (m_children.GetCount() == 0)
1412 return wxSize(10,10);
1413
1414 m_stretchable = 0;
1415 m_minWidth = 0;
1416 m_minHeight = 0;
1417 m_fixedWidth = 0;
1418 m_fixedHeight = 0;
1419
1420 // Find how long each stretch unit needs to be
1421 int stretchSize = 1;
1422 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1423
1424 while (node)
1425 {
1426 wxSizerItem *item = node->GetData();
1427
1428 if (item->IsShown() && item->GetProportion() != 0)
1429 {
1430 int stretch = item->GetProportion();
1431 wxSize size( item->CalcMin() );
1432 int sizePerStretch;
1433 // Integer division rounded up is (a + b - 1) / b
1434 if (m_orient == wxHORIZONTAL)
1435 sizePerStretch = ( size.x + stretch - 1 ) / stretch;
1436 else
1437 sizePerStretch = ( size.y + stretch - 1 ) / stretch;
1438 if (sizePerStretch > stretchSize)
1439 stretchSize = sizePerStretch;
1440 }
1441 node = node->GetNext();
1442 }
1443
1444 // Calculate overall minimum size
1445 node = m_children.GetFirst();
1446 while (node)
1447 {
1448 wxSizerItem *item = node->GetData();
1449
1450 if (item->IsShown())
1451 {
1452 m_stretchable += item->GetProportion();
1453
1454 wxSize size( item->CalcMin() );
1455 if (item->GetProportion() != 0)
1456 {
1457 if (m_orient == wxHORIZONTAL)
1458 size.x = stretchSize * item->GetProportion();
1459 else
1460 size.y = stretchSize * item->GetProportion();
1461 }
1462
1463 if (m_orient == wxHORIZONTAL)
1464 {
1465 m_minWidth += size.x;
1466 m_minHeight = wxMax( m_minHeight, size.y );
1467 }
1468 else
1469 {
1470 m_minHeight += size.y;
1471 m_minWidth = wxMax( m_minWidth, size.x );
1472 }
1473
1474 if (item->GetProportion() == 0)
1475 {
1476 if (m_orient == wxVERTICAL)
1477 {
1478 m_fixedHeight += size.y;
1479 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1480 }
1481 else
1482 {
1483 m_fixedWidth += size.x;
1484 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1485 }
1486 }
1487 }
1488 node = node->GetNext();
1489 }
1490
1491 return wxSize( m_minWidth, m_minHeight );
1492 }
1493
1494 //---------------------------------------------------------------------------
1495 // wxStaticBoxSizer
1496 //---------------------------------------------------------------------------
1497
1498 #if wxUSE_STATBOX
1499
1500 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1501 : wxBoxSizer( orient )
1502 , m_staticBox( box )
1503 {
1504 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1505 }
1506
1507 static void GetStaticBoxBorders( wxStaticBox *box,
1508 int *borderTop,
1509 int *borderOther)
1510 {
1511 // this has to be done platform by platform as there is no way to
1512 // guess the thickness of a wxStaticBox border
1513 #ifdef __WXCOCOA__
1514 box->GetBordersForSizer(borderTop,borderOther);
1515 #else // __WXCOCOA__
1516 #ifdef __WXGTK__
1517 if ( box->GetLabel().IsEmpty() )
1518 *borderTop = 5;
1519 else
1520 #endif // __WXGTK__
1521 *borderTop = box->GetCharHeight();
1522
1523 *borderOther = 5;
1524 #endif // __WXCOCOA__
1525 }
1526
1527 void wxStaticBoxSizer::RecalcSizes()
1528 {
1529 int top_border, other_border;
1530 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1531
1532 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1533
1534 wxPoint old_pos( m_position );
1535 m_position.x += other_border;
1536 m_position.y += top_border;
1537 wxSize old_size( m_size );
1538 m_size.x -= 2*other_border;
1539 m_size.y -= top_border + other_border;
1540
1541 wxBoxSizer::RecalcSizes();
1542
1543 m_position = old_pos;
1544 m_size = old_size;
1545 }
1546
1547 wxSize wxStaticBoxSizer::CalcMin()
1548 {
1549 int top_border, other_border;
1550 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1551
1552 wxSize ret( wxBoxSizer::CalcMin() );
1553 ret.x += 2*other_border;
1554 ret.y += other_border + top_border;
1555
1556 return ret;
1557 }
1558
1559 #endif // wxUSE_STATBOX
1560
1561 // ----------------------------------------------------------------------------
1562 // wxNotebookSizer
1563 // ----------------------------------------------------------------------------
1564
1565 #if wxUSE_BOOKCTRL
1566
1567 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1568 : m_bookctrl(bookctrl)
1569 {
1570 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1571 }
1572
1573 void wxBookCtrlSizer::RecalcSizes()
1574 {
1575 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1576 }
1577
1578 wxSize wxBookCtrlSizer::CalcMin()
1579 {
1580 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1581
1582 sizeBorder.x += 5;
1583 sizeBorder.y += 5;
1584
1585 if ( m_bookctrl->GetPageCount() == 0 )
1586 {
1587 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1588 }
1589
1590 int maxX = 0;
1591 int maxY = 0;
1592
1593 wxWindowList::compatibility_iterator
1594 node = m_bookctrl->GetChildren().GetFirst();
1595 while (node)
1596 {
1597 wxWindow *item = node->GetData();
1598 wxSizer *itemsizer = item->GetSizer();
1599
1600 if (itemsizer)
1601 {
1602 wxSize subsize( itemsizer->CalcMin() );
1603
1604 if (subsize.x > maxX)
1605 maxX = subsize.x;
1606 if (subsize.y > maxY)
1607 maxY = subsize.y;
1608 }
1609
1610 node = node->GetNext();
1611 }
1612
1613 return wxSize( maxX, maxY ) + sizeBorder;
1614 }
1615
1616 #endif // wxUSE_BOOKCTRL
1617