]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
return the index of the inserted/appended item
[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->SetClientSize( 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 WXUNUSED(idx) )
1292 {
1293 }
1294
1295 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1296 {
1297 m_growableCols.Add( idx );
1298 m_growableColsProportions.Add( proportion );
1299 }
1300
1301 void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx) )
1302 {
1303 }
1304
1305 //---------------------------------------------------------------------------
1306 // wxBoxSizer
1307 //---------------------------------------------------------------------------
1308
1309 wxBoxSizer::wxBoxSizer( int orient )
1310 : m_orient( orient )
1311 {
1312 }
1313
1314 void wxBoxSizer::RecalcSizes()
1315 {
1316 if (m_children.GetCount() == 0)
1317 return;
1318
1319 int delta = 0;
1320 int extra = 0;
1321 if (m_stretchable)
1322 {
1323 if (m_orient == wxHORIZONTAL)
1324 {
1325 delta = (m_size.x - m_fixedWidth) / m_stretchable;
1326 extra = (m_size.x - m_fixedWidth) % m_stretchable;
1327 }
1328 else
1329 {
1330 delta = (m_size.y - m_fixedHeight) / m_stretchable;
1331 extra = (m_size.y - m_fixedHeight) % m_stretchable;
1332 }
1333 }
1334
1335 wxPoint pt( m_position );
1336
1337 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1338 while (node)
1339 {
1340 wxSizerItem *item = node->GetData();
1341
1342 if (item->IsShown())
1343 {
1344 int weight = 1;
1345 if (item->GetProportion())
1346 weight = item->GetProportion();
1347
1348 wxSize size( item->CalcMin() );
1349
1350 if (m_orient == wxVERTICAL)
1351 {
1352 wxCoord height = size.y;
1353 if (item->GetProportion())
1354 {
1355 height = (delta * weight) + extra;
1356 extra = 0; // only the first item will get the remainder as extra size
1357 }
1358
1359 wxPoint child_pos( pt );
1360 wxSize child_size( wxSize( size.x, height) );
1361
1362 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1363 child_size.x = m_size.x;
1364 else if (item->GetFlag() & wxALIGN_RIGHT)
1365 child_pos.x += m_size.x - size.x;
1366 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1367 // XXX wxCENTER is added for backward compatibility;
1368 // wxALIGN_CENTER should be used in new code
1369 child_pos.x += (m_size.x - size.x) / 2;
1370
1371 item->SetDimension( child_pos, child_size );
1372
1373 pt.y += height;
1374 }
1375 else
1376 {
1377 wxCoord width = size.x;
1378 if (item->GetProportion())
1379 {
1380 width = (delta * weight) + extra;
1381 extra = 0; // only the first item will get the remainder as extra size
1382 }
1383
1384 wxPoint child_pos( pt );
1385 wxSize child_size( wxSize(width, size.y) );
1386
1387 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1388 child_size.y = m_size.y;
1389 else if (item->GetFlag() & wxALIGN_BOTTOM)
1390 child_pos.y += m_size.y - size.y;
1391 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1392 // XXX wxCENTER is added for backward compatibility;
1393 // wxALIGN_CENTER should be used in new code
1394 child_pos.y += (m_size.y - size.y) / 2;
1395
1396 item->SetDimension( child_pos, child_size );
1397
1398 pt.x += width;
1399 }
1400 }
1401
1402 node = node->GetNext();
1403 }
1404 }
1405
1406 wxSize wxBoxSizer::CalcMin()
1407 {
1408 if (m_children.GetCount() == 0)
1409 return wxSize(10,10);
1410
1411 m_stretchable = 0;
1412 m_minWidth = 0;
1413 m_minHeight = 0;
1414 m_fixedWidth = 0;
1415 m_fixedHeight = 0;
1416
1417 // Find how long each stretch unit needs to be
1418 int stretchSize = 1;
1419 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1420
1421 while (node)
1422 {
1423 wxSizerItem *item = node->GetData();
1424
1425 if (item->IsShown() && item->GetProportion() != 0)
1426 {
1427 int stretch = item->GetProportion();
1428 wxSize size( item->CalcMin() );
1429 int sizePerStretch;
1430 // Integer division rounded up is (a + b - 1) / b
1431 if (m_orient == wxHORIZONTAL)
1432 sizePerStretch = ( size.x + stretch - 1 ) / stretch;
1433 else
1434 sizePerStretch = ( size.y + stretch - 1 ) / stretch;
1435 if (sizePerStretch > stretchSize)
1436 stretchSize = sizePerStretch;
1437 }
1438 node = node->GetNext();
1439 }
1440
1441 // Calculate overall minimum size
1442 node = m_children.GetFirst();
1443 while (node)
1444 {
1445 wxSizerItem *item = node->GetData();
1446
1447 if (item->IsShown())
1448 {
1449 m_stretchable += item->GetProportion();
1450
1451 wxSize size( item->CalcMin() );
1452 if (item->GetProportion() != 0)
1453 {
1454 if (m_orient == wxHORIZONTAL)
1455 size.x = stretchSize * item->GetProportion();
1456 else
1457 size.y = stretchSize * item->GetProportion();
1458 }
1459
1460 if (m_orient == wxHORIZONTAL)
1461 {
1462 m_minWidth += size.x;
1463 m_minHeight = wxMax( m_minHeight, size.y );
1464 }
1465 else
1466 {
1467 m_minHeight += size.y;
1468 m_minWidth = wxMax( m_minWidth, size.x );
1469 }
1470
1471 if (item->GetProportion() == 0)
1472 {
1473 if (m_orient == wxVERTICAL)
1474 {
1475 m_fixedHeight += size.y;
1476 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1477 }
1478 else
1479 {
1480 m_fixedWidth += size.x;
1481 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1482 }
1483 }
1484 }
1485 node = node->GetNext();
1486 }
1487
1488 return wxSize( m_minWidth, m_minHeight );
1489 }
1490
1491 //---------------------------------------------------------------------------
1492 // wxStaticBoxSizer
1493 //---------------------------------------------------------------------------
1494
1495 #if wxUSE_STATBOX
1496
1497 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1498 : wxBoxSizer( orient )
1499 , m_staticBox( box )
1500 {
1501 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1502 }
1503
1504 static void GetStaticBoxBorders( wxStaticBox *box,
1505 int *borderTop,
1506 int *borderOther)
1507 {
1508 // this has to be done platform by platform as there is no way to
1509 // guess the thickness of a wxStaticBox border
1510 #ifdef __WXCOCOA__
1511 box->GetBordersForSizer(borderTop,borderOther);
1512 #else // __WXCOCOA__
1513 #ifdef __WXGTK__
1514 if ( box->GetLabel().IsEmpty() )
1515 *borderTop = 5;
1516 else
1517 #endif // __WXGTK__
1518 *borderTop = box->GetCharHeight();
1519
1520 *borderOther = 5;
1521 #endif // __WXCOCOA__
1522 }
1523
1524 void wxStaticBoxSizer::RecalcSizes()
1525 {
1526 int top_border, other_border;
1527 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1528
1529 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1530
1531 wxPoint old_pos( m_position );
1532 m_position.x += other_border;
1533 m_position.y += top_border;
1534 wxSize old_size( m_size );
1535 m_size.x -= 2*other_border;
1536 m_size.y -= top_border + other_border;
1537
1538 wxBoxSizer::RecalcSizes();
1539
1540 m_position = old_pos;
1541 m_size = old_size;
1542 }
1543
1544 wxSize wxStaticBoxSizer::CalcMin()
1545 {
1546 int top_border, other_border;
1547 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1548
1549 wxSize ret( wxBoxSizer::CalcMin() );
1550 ret.x += 2*other_border;
1551 ret.y += other_border + top_border;
1552
1553 return ret;
1554 }
1555
1556 #endif // wxUSE_STATBOX
1557
1558 // ----------------------------------------------------------------------------
1559 // wxNotebookSizer
1560 // ----------------------------------------------------------------------------
1561
1562 #if wxUSE_BOOKCTRL
1563
1564 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1565 : m_bookctrl(bookctrl)
1566 {
1567 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1568 }
1569
1570 void wxBookCtrlSizer::RecalcSizes()
1571 {
1572 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1573 }
1574
1575 wxSize wxBookCtrlSizer::CalcMin()
1576 {
1577 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1578
1579 sizeBorder.x += 5;
1580 sizeBorder.y += 5;
1581
1582 if ( m_bookctrl->GetPageCount() == 0 )
1583 {
1584 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1585 }
1586
1587 int maxX = 0;
1588 int maxY = 0;
1589
1590 wxWindowList::compatibility_iterator
1591 node = m_bookctrl->GetChildren().GetFirst();
1592 while (node)
1593 {
1594 wxWindow *item = node->GetData();
1595 wxSizer *itemsizer = item->GetSizer();
1596
1597 if (itemsizer)
1598 {
1599 wxSize subsize( itemsizer->CalcMin() );
1600
1601 if (subsize.x > maxX)
1602 maxX = subsize.x;
1603 if (subsize.y > maxY)
1604 maxY = subsize.y;
1605 }
1606
1607 node = node->GetNext();
1608 }
1609
1610 return wxSize( maxX, maxY ) + sizeBorder;
1611 }
1612
1613
1614 #if wxUSE_NOTEBOOK
1615
1616 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1617 : wxBookCtrlSizer(nb)
1618 {
1619 }
1620
1621 #endif // wxUSE_NOTEBOOOK
1622 #endif // wxUSE_BOOKCTRL
1623