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