]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/sizer.cpp
fix for crash on 64 bit platforms (patch 1028942)
[wxWidgets.git] / src / common / sizer.cpp
... / ...
CommitLineData
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
38IMPLEMENT_CLASS(wxSizerItem, wxObject)
39IMPLEMENT_CLASS(wxSizer, wxObject)
40IMPLEMENT_CLASS(wxGridSizer, wxSizer)
41IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
42IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
43#if wxUSE_STATBOX
44IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
45#endif
46
47WX_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
85wxSizerItem::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
99wxSizerItem::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
118wxSizerItem::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
132wxSizerItem::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
144wxSizerItem::~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
159wxSize 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
181wxSize 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
202wxSize 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
219void 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
281void 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
293bool wxSizerItem::IsWindow() const
294{
295 return (m_window != NULL);
296}
297
298bool wxSizerItem::IsSizer() const
299{
300 return (m_sizer != NULL);
301}
302
303bool wxSizerItem::IsSpacer() const
304{
305 return (m_window == NULL) && (m_sizer == NULL);
306}
307
308void 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
320void wxSizerItem::SetOption( int option )
321{
322 SetProportion( option );
323}
324
325int wxSizerItem::GetOption() const
326{
327 return GetProportion();
328}
329
330
331//---------------------------------------------------------------------------
332// wxSizer
333//---------------------------------------------------------------------------
334
335wxSizer::wxSizer()
336 : m_minSize( wxSize( 0, 0 ) )
337{
338}
339
340wxSizer::~wxSizer()
341{
342 WX_CLEAR_LIST(wxSizerItemList, m_children);
343}
344
345void 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
351void 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
356void 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
361void wxSizer::Add( wxSizerItem *item )
362{
363 m_children.Append( item );
364
365 if( item->GetWindow() )
366 item->GetWindow()->SetContainingSizer( this );
367}
368
369void wxSizer::AddSpacer(int size)
370{
371 Add(size, size);
372}
373
374void wxSizer::AddStretchSpacer(int prop)
375{
376 Add(0, 0, prop);
377}
378
379void 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
385void 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
390void 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
395void wxSizer::Prepend( wxSizerItem *item )
396{
397 m_children.Insert( item );
398
399 if( item->GetWindow() )
400 item->GetWindow()->SetContainingSizer( this );
401}
402
403void wxSizer::PrependSpacer(int size)
404{
405 Prepend(size, size);
406}
407
408void wxSizer::PrependStretchSpacer(int prop)
409{
410 Prepend(0, 0, prop);
411}
412
413void 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
425void 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
436void 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
448void 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
456void wxSizer::InsertSpacer(size_t index, int size)
457{
458 Insert(index, size, size);
459}
460
461void wxSizer::InsertStretchSpacer(size_t index, int prop)
462{
463 Insert(index, 0, 0, prop);
464}
465
466bool wxSizer::Remove( wxWindow *window )
467{
468 return Detach( window );
469}
470
471bool 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
493bool 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
513bool 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
535bool 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
557bool 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
579void 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
600void 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
612wxSize 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
622void 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
633void 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
643void 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
656void 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
669wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
670{
671 return window->GetMaxSize();
672}
673
674wxSize 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
689wxSize 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
704wxSize 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
720wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
721{
722 return GetMinSize(); // Already returns client size.
723}
724
725wxSize 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
740void 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
749wxSize 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
757void wxSizer::DoSetMinSize( int width, int height )
758{
759 m_minSize.x = width;
760 m_minSize.y = height;
761}
762
763bool 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
801bool 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
839bool 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
861bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
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
874 return true;
875 }
876 else if (recursive && item->IsSizer())
877 {
878 if (item->GetSizer()->Show(window, show, recursive))
879 return true;
880 }
881
882 node = node->GetNext();
883 }
884
885 return false;
886}
887
888bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
889{
890 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
891
892 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
893 while (node)
894 {
895 wxSizerItem *item = node->GetData();
896
897 if (item->GetSizer() == sizer)
898 {
899 item->Show( show );
900
901 return true;
902 }
903 else if (recursive && item->IsSizer())
904 {
905 if (item->GetSizer()->Show(sizer, show, recursive))
906 return true;
907 }
908
909 node = node->GetNext();
910 }
911
912 return false;
913}
914
915bool wxSizer::Show( size_t index, bool show)
916{
917 wxCHECK_MSG( index < m_children.GetCount(),
918 false,
919 _T("Show index is out of range") );
920
921 m_children.Item( index )->GetData()->Show( show );
922
923 return true;
924}
925
926void wxSizer::ShowItems( bool show )
927{
928 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
929 while (node)
930 {
931 node->GetData()->Show( show );
932 node = node->GetNext();
933 }
934}
935
936bool wxSizer::IsShown( wxWindow *window ) const
937{
938 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
939 while (node)
940 {
941 wxSizerItem *item = node->GetData();
942
943 if (item->GetWindow() == window)
944 {
945 return item->IsShown();
946 }
947 node = node->GetNext();
948 }
949
950 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
951
952 return false;
953}
954
955bool wxSizer::IsShown( wxSizer *sizer ) const
956{
957 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
958 while (node)
959 {
960 wxSizerItem *item = node->GetData();
961
962 if (item->GetSizer() == sizer)
963 {
964 return item->IsShown();
965 }
966 node = node->GetNext();
967 }
968
969 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
970
971 return false;
972}
973
974bool wxSizer::IsShown( size_t index ) const
975{
976 wxCHECK_MSG( index < m_children.GetCount(),
977 false,
978 _T("IsShown index is out of range") );
979
980 return m_children.Item( index )->GetData()->IsShown();
981}
982
983
984//---------------------------------------------------------------------------
985// wxGridSizer
986//---------------------------------------------------------------------------
987
988wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
989 : m_rows( rows )
990 , m_cols( cols )
991 , m_vgap( vgap )
992 , m_hgap( hgap )
993{
994 if (m_rows == 0 && m_cols == 0)
995 m_rows = 1;
996}
997
998wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
999 : m_rows( 0 )
1000 , m_cols( cols )
1001 , m_vgap( vgap )
1002 , m_hgap( hgap )
1003{
1004 if (m_rows == 0 && m_cols == 0)
1005 m_rows = 1;
1006}
1007
1008int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
1009{
1010 int nitems = m_children.GetCount();
1011 if ( nitems)
1012 {
1013 if ( m_cols )
1014 {
1015 ncols = m_cols;
1016 nrows = (nitems + m_cols - 1) / m_cols;
1017 }
1018 else if ( m_rows )
1019 {
1020 ncols = (nitems + m_rows - 1) / m_rows;
1021 nrows = m_rows;
1022 }
1023 else // 0 columns, 0 rows?
1024 {
1025 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
1026
1027 nrows = ncols = 0;
1028 }
1029 }
1030
1031 return nitems;
1032}
1033
1034void wxGridSizer::RecalcSizes()
1035{
1036 int nitems, nrows, ncols;
1037 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1038 return;
1039
1040 wxSize sz( GetSize() );
1041 wxPoint pt( GetPosition() );
1042
1043 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
1044 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
1045
1046 int x = pt.x;
1047 for (int c = 0; c < ncols; c++)
1048 {
1049 int y = pt.y;
1050 for (int r = 0; r < nrows; r++)
1051 {
1052 int i = r * ncols + c;
1053 if (i < nitems)
1054 {
1055 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1056
1057 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
1058
1059 SetItemBounds( node->GetData(), x, y, w, h);
1060 }
1061 y = y + h + m_vgap;
1062 }
1063 x = x + w + m_hgap;
1064 }
1065}
1066
1067wxSize wxGridSizer::CalcMin()
1068{
1069 int nrows, ncols;
1070 if ( CalcRowsCols(nrows, ncols) == 0 )
1071 return wxSize(10, 10);
1072
1073 // Find the max width and height for any component
1074 int w = 0;
1075 int h = 0;
1076
1077 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1078 while (node)
1079 {
1080 wxSizerItem *item = node->GetData();
1081 wxSize sz( item->CalcMin() );
1082
1083 w = wxMax( w, sz.x );
1084 h = wxMax( h, sz.y );
1085
1086 node = node->GetNext();
1087 }
1088
1089 return wxSize( ncols * w + (ncols-1) * m_hgap,
1090 nrows * h + (nrows-1) * m_vgap );
1091}
1092
1093void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1094{
1095 wxPoint pt( x,y );
1096 wxSize sz( item->GetMinSizeWithBorder() );
1097 int flag = item->GetFlag();
1098
1099 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1100 {
1101 sz = wxSize(w, h);
1102 }
1103 else
1104 {
1105 if (flag & wxALIGN_CENTER_HORIZONTAL)
1106 {
1107 pt.x = x + (w - sz.x) / 2;
1108 }
1109 else if (flag & wxALIGN_RIGHT)
1110 {
1111 pt.x = x + (w - sz.x);
1112 }
1113
1114 if (flag & wxALIGN_CENTER_VERTICAL)
1115 {
1116 pt.y = y + (h - sz.y) / 2;
1117 }
1118 else if (flag & wxALIGN_BOTTOM)
1119 {
1120 pt.y = y + (h - sz.y);
1121 }
1122 }
1123
1124 item->SetDimension(pt, sz);
1125}
1126
1127//---------------------------------------------------------------------------
1128// wxFlexGridSizer
1129//---------------------------------------------------------------------------
1130
1131wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1132 : wxGridSizer( rows, cols, vgap, hgap ),
1133 m_flexDirection(wxBOTH),
1134 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1135{
1136}
1137
1138wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1139 : wxGridSizer( cols, vgap, hgap ),
1140 m_flexDirection(wxBOTH),
1141 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1142{
1143}
1144
1145wxFlexGridSizer::~wxFlexGridSizer()
1146{
1147}
1148
1149void wxFlexGridSizer::RecalcSizes()
1150{
1151 int nitems, nrows, ncols;
1152 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1153 return;
1154
1155 wxPoint pt( GetPosition() );
1156 wxSize sz( GetSize() );
1157
1158 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
1159
1160 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1161
1162 int x = pt.x;
1163 for (int c = 0; c < ncols; c++)
1164 {
1165 int y = pt.y;
1166 for (int r = 0; r < nrows; r++)
1167 {
1168 int i = r * ncols + c;
1169 if (i < nitems)
1170 {
1171 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1172
1173 wxASSERT_MSG( node, _T("Failed to find node") );
1174
1175 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1176 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1177
1178 SetItemBounds( node->GetData(), x, y, w, h);
1179 }
1180 y = y + m_rowHeights[r] + m_vgap;
1181 }
1182 x = x + m_colWidths[c] + m_hgap;
1183 }
1184}
1185
1186wxSize wxFlexGridSizer::CalcMin()
1187{
1188 int nrows,
1189 ncols;
1190 size_t i, s;
1191
1192 // Number of rows/columns can change as items are added or removed.
1193 if ( !CalcRowsCols(nrows, ncols) )
1194 return wxSize(10, 10);
1195
1196 m_rowHeights.SetCount(nrows);
1197 m_colWidths.SetCount(ncols);
1198
1199 // We have to recalcuate the sizes in case the item minimum size has
1200 // changed since the previous layout, or the item has been hidden using
1201 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1202 // dimension of the row/column will be -1, indicating that the column
1203 // itself is hidden.
1204 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1205 m_rowHeights[ i ] = -1;
1206 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1207 m_colWidths[ i ] = -1;
1208
1209 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1210
1211 i = 0;
1212 while (node)
1213 {
1214 wxSizerItem *item = node->GetData();
1215 if ( item->IsShown() )
1216 {
1217 wxSize sz( item->CalcMin() );
1218 int row = i / ncols;
1219 int col = i % ncols;
1220
1221 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1222 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1223 }
1224
1225 node = node->GetNext();
1226 i++;
1227 }
1228
1229 AdjustForFlexDirection();
1230
1231 // Sum total minimum size, including gaps between rows/columns.
1232 // -1 is used as a magic number meaning empty column.
1233 int width = 0;
1234 for (int col = 0; col < ncols; col++)
1235 if ( m_colWidths[ col ] != -1 )
1236 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1237
1238 int height = 0;
1239 for (int row = 0; row < nrows; row++)
1240 if ( m_rowHeights[ row ] != -1 )
1241 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1242
1243 m_calculatedMinSize = wxSize( width, height );
1244 return m_calculatedMinSize;
1245}
1246
1247void wxFlexGridSizer::AdjustForFlexDirection()
1248{
1249 // the logic in CalcMin works when we resize flexibly in both directions
1250 // but maybe this is not the case
1251 if ( m_flexDirection != wxBOTH )
1252 {
1253 // select the array corresponding to the direction in which we do *not*
1254 // resize flexibly
1255 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1256 : m_rowHeights;
1257
1258 const int count = array.GetCount();
1259
1260 // find the largest value in this array
1261 int n, largest = 0;
1262 for ( n = 0; n < count; ++n )
1263 {
1264 if ( array[n] > largest )
1265 largest = array[n];
1266 }
1267
1268 // and now fill it with the largest value
1269 for ( n = 0; n < count; ++n )
1270 {
1271 array[n] = largest;
1272 }
1273 }
1274}
1275
1276
1277void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1278 int nrows, int ncols)
1279{
1280 // what to do with the rows? by default, resize them proportionally
1281 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1282 {
1283 int sum_proportions = 0;
1284 int growable_space = 0;
1285 int num = 0;
1286 size_t idx;
1287 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1288 {
1289 // Since the number of rows/columns can change as items are
1290 // inserted/deleted, we need to verify at runtime that the
1291 // requested growable rows/columns are still valid.
1292 if (m_growableRows[idx] >= nrows)
1293 continue;
1294
1295 // If all items in a row/column are hidden, that row/column will
1296 // have a dimension of -1. This causes the row/column to be
1297 // hidden completely.
1298 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1299 continue;
1300 sum_proportions += m_growableRowsProportions[idx];
1301 growable_space += m_rowHeights[ m_growableRows[idx] ];
1302 num++;
1303 }
1304
1305 if (num > 0)
1306 {
1307 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1308 {
1309 if (m_growableRows[idx] >= nrows )
1310 continue;
1311 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1312 m_rowHeights[ m_growableRows[idx] ] = 0;
1313 else
1314 {
1315 int delta = (sz.y - minsz.y);
1316 if (sum_proportions == 0)
1317 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1318 else
1319 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1320 m_rowHeights[ m_growableRows[idx] ] = delta;
1321 }
1322 }
1323 }
1324 }
1325 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1326 {
1327 // rounding problem?
1328 for ( int row = 0; row < nrows; ++row )
1329 m_rowHeights[ row ] = sz.y / nrows;
1330 }
1331
1332 // the same logic as above but for the columns
1333 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1334 {
1335 int sum_proportions = 0;
1336 int growable_space = 0;
1337 int num = 0;
1338 size_t idx;
1339 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1340 {
1341 // Since the number of rows/columns can change as items are
1342 // inserted/deleted, we need to verify at runtime that the
1343 // requested growable rows/columns are still valid.
1344 if (m_growableCols[idx] >= ncols)
1345 continue;
1346
1347 // If all items in a row/column are hidden, that row/column will
1348 // have a dimension of -1. This causes the column to be hidden
1349 // completely.
1350 if (m_colWidths[ m_growableCols[idx] ] == -1)
1351 continue;
1352 sum_proportions += m_growableColsProportions[idx];
1353 growable_space += m_colWidths[ m_growableCols[idx] ];
1354 num++;
1355 }
1356
1357 if (num > 0)
1358 {
1359 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1360 {
1361 if (m_growableCols[idx] >= ncols )
1362 continue;
1363 if (m_colWidths[ m_growableCols[idx] ] == -1)
1364 m_colWidths[ m_growableCols[idx] ] = 0;
1365 else
1366 {
1367 int delta = (sz.x - minsz.x);
1368 if (sum_proportions == 0)
1369 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1370 else
1371 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1372 m_colWidths[ m_growableCols[idx] ] = delta;
1373 }
1374 }
1375 }
1376 }
1377 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1378 {
1379 for ( int col=0; col < ncols; ++col )
1380 m_colWidths[ col ] = sz.x / ncols;
1381 }
1382}
1383
1384
1385void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1386{
1387 m_growableRows.Add( idx );
1388 m_growableRowsProportions.Add( proportion );
1389}
1390
1391void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1392{
1393 m_growableRows.Remove( idx );
1394}
1395
1396void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1397{
1398 m_growableCols.Add( idx );
1399 m_growableColsProportions.Add( proportion );
1400}
1401
1402void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1403{
1404 m_growableCols.Remove( idx );
1405}
1406
1407//---------------------------------------------------------------------------
1408// wxBoxSizer
1409//---------------------------------------------------------------------------
1410
1411wxBoxSizer::wxBoxSizer( int orient )
1412 : m_orient( orient )
1413{
1414}
1415
1416void wxBoxSizer::RecalcSizes()
1417{
1418 if (m_children.GetCount() == 0)
1419 return;
1420
1421 int delta = 0;
1422 if (m_stretchable)
1423 {
1424 if (m_orient == wxHORIZONTAL)
1425 delta = m_size.x - m_fixedWidth;
1426 else
1427 delta = m_size.y - m_fixedHeight;
1428 }
1429
1430 wxPoint pt( m_position );
1431
1432 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1433 while (node)
1434 {
1435 wxSizerItem *item = node->GetData();
1436
1437 if (item->IsShown())
1438 {
1439 wxSize size( item->GetMinSizeWithBorder() );
1440
1441 if (m_orient == wxVERTICAL)
1442 {
1443 wxCoord height = size.y;
1444 if (item->GetProportion())
1445 {
1446 // Because of at least one visible item has non-zero
1447 // proportion then m_stretchable is not zero
1448 height = (delta * item->GetProportion()) / m_stretchable;
1449 }
1450
1451 wxPoint child_pos( pt );
1452 wxSize child_size( wxSize( size.x, height) );
1453
1454 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1455 child_size.x = m_size.x;
1456 else if (item->GetFlag() & wxALIGN_RIGHT)
1457 child_pos.x += m_size.x - size.x;
1458 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1459 // XXX wxCENTER is added for backward compatibility;
1460 // wxALIGN_CENTER should be used in new code
1461 child_pos.x += (m_size.x - size.x) / 2;
1462
1463 item->SetDimension( child_pos, child_size );
1464
1465 pt.y += height;
1466 }
1467 else
1468 {
1469 wxCoord width = size.x;
1470 if (item->GetProportion())
1471 {
1472 // Because of at least one visible item has non-zero
1473 // proportion then m_stretchable is not zero
1474 width = (delta * item->GetProportion()) / m_stretchable;
1475 }
1476
1477 wxPoint child_pos( pt );
1478 wxSize child_size( wxSize(width, size.y) );
1479
1480 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1481 child_size.y = m_size.y;
1482 else if (item->GetFlag() & wxALIGN_BOTTOM)
1483 child_pos.y += m_size.y - size.y;
1484 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1485 // XXX wxCENTER is added for backward compatibility;
1486 // wxALIGN_CENTER should be used in new code
1487 child_pos.y += (m_size.y - size.y) / 2;
1488
1489 item->SetDimension( child_pos, child_size );
1490
1491 pt.x += width;
1492 }
1493 }
1494
1495 node = node->GetNext();
1496 }
1497}
1498
1499wxSize wxBoxSizer::CalcMin()
1500{
1501 if (m_children.GetCount() == 0)
1502 return wxSize(10,10);
1503
1504 m_stretchable = 0;
1505 m_minWidth = 0;
1506 m_minHeight = 0;
1507 m_fixedWidth = 0;
1508 m_fixedHeight = 0;
1509
1510 // precalc item minsizes and count proportions
1511 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1512 while (node)
1513 {
1514 wxSizerItem *item = node->GetData();
1515
1516 if (item->IsShown())
1517 item->CalcMin(); // result is stored in the item
1518
1519 if (item->IsShown() && item->GetProportion() != 0)
1520 m_stretchable += item->GetProportion();
1521
1522 node = node->GetNext();
1523 }
1524
1525 // Total minimum size (width or height) of sizer
1526 int maxMinSize = 0;
1527
1528 node = m_children.GetFirst();
1529 while (node)
1530 {
1531 wxSizerItem *item = node->GetData();
1532
1533 if (item->IsShown() && item->GetProportion() != 0)
1534 {
1535 int stretch = item->GetProportion();
1536 wxSize size( item->GetMinSizeWithBorder() );
1537 int minSize;
1538
1539 // Integer division rounded up is (a + b - 1) / b
1540 // Round up needed in order to guarantee that all
1541 // all items will have size not less then their min size
1542 if (m_orient == wxHORIZONTAL)
1543 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1544 else
1545 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1546
1547 if (minSize > maxMinSize)
1548 maxMinSize = minSize;
1549 }
1550 node = node->GetNext();
1551 }
1552
1553 // Calculate overall minimum size
1554 node = m_children.GetFirst();
1555 while (node)
1556 {
1557 wxSizerItem *item = node->GetData();
1558
1559 if (item->IsShown())
1560 {
1561 wxSize size( item->GetMinSizeWithBorder() );
1562 if (item->GetProportion() != 0)
1563 {
1564 if (m_orient == wxHORIZONTAL)
1565 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1566 else
1567 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1568 }
1569 else
1570 {
1571 if (m_orient == wxVERTICAL)
1572 {
1573 m_fixedHeight += size.y;
1574 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1575 }
1576 else
1577 {
1578 m_fixedWidth += size.x;
1579 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1580 }
1581 }
1582
1583 if (m_orient == wxHORIZONTAL)
1584 {
1585 m_minWidth += size.x;
1586 m_minHeight = wxMax( m_minHeight, size.y );
1587 }
1588 else
1589 {
1590 m_minHeight += size.y;
1591 m_minWidth = wxMax( m_minWidth, size.x );
1592 }
1593 }
1594 node = node->GetNext();
1595 }
1596
1597 return wxSize( m_minWidth, m_minHeight );
1598}
1599
1600//---------------------------------------------------------------------------
1601// wxStaticBoxSizer
1602//---------------------------------------------------------------------------
1603
1604#if wxUSE_STATBOX
1605
1606wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1607 : wxBoxSizer( orient )
1608 , m_staticBox( box )
1609{
1610 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1611}
1612
1613static void GetStaticBoxBorders( wxStaticBox *box,
1614 int *borderTop,
1615 int *borderOther)
1616{
1617 // this has to be done platform by platform as there is no way to
1618 // guess the thickness of a wxStaticBox border
1619#ifdef __WXCOCOA__
1620 box->GetBordersForSizer(borderTop,borderOther);
1621#elif defined(__WXMAC__)
1622
1623 static int extraTop = -1; // Uninitted
1624 static int other = 5;
1625
1626 if ( extraTop == -1 )
1627 {
1628 // The minimal border used for the top. Later on the staticbox'
1629 // font height is added to this.
1630 extraTop = 0;
1631
1632 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1633 {
1634 // As indicated by the HIG, Panther needs an extra border of 11
1635 // pixels (otherwise overlapping occurs at the top). The "other"
1636 // border has to be 11.
1637 extraTop = 11;
1638 other = 11;
1639 }
1640
1641 }
1642
1643 *borderTop = extraTop + box->GetCharHeight();
1644 *borderOther = other;
1645
1646#else
1647#ifdef __WXGTK__
1648 if ( box->GetLabel().IsEmpty() )
1649 *borderTop = 5;
1650 else
1651#endif // __WXGTK__
1652 *borderTop = box->GetCharHeight();
1653
1654 *borderOther = 5;
1655#endif // __WXCOCOA__
1656}
1657
1658void wxStaticBoxSizer::RecalcSizes()
1659{
1660 int top_border, other_border;
1661 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1662
1663 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1664
1665 wxPoint old_pos( m_position );
1666 m_position.x += other_border;
1667 m_position.y += top_border;
1668 wxSize old_size( m_size );
1669 m_size.x -= 2*other_border;
1670 m_size.y -= top_border + other_border;
1671
1672 wxBoxSizer::RecalcSizes();
1673
1674 m_position = old_pos;
1675 m_size = old_size;
1676}
1677
1678wxSize wxStaticBoxSizer::CalcMin()
1679{
1680 int top_border, other_border;
1681 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1682
1683 wxSize ret( wxBoxSizer::CalcMin() );
1684 ret.x += 2*other_border;
1685 ret.y += other_border + top_border;
1686
1687 return ret;
1688}
1689
1690void wxStaticBoxSizer::ShowItems( bool show )
1691{
1692 m_staticBox->Show( show );
1693 wxBoxSizer::ShowItems( show );
1694}
1695
1696#endif // wxUSE_STATBOX
1697
1698
1699#if WXWIN_COMPATIBILITY_2_4
1700
1701// ----------------------------------------------------------------------------
1702// wxNotebookSizer
1703// ----------------------------------------------------------------------------
1704
1705#if wxUSE_BOOKCTRL
1706IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
1707#if wxUSE_NOTEBOOK
1708IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
1709#endif // wxUSE_NOTEBOOK
1710#endif // wxUSE_BOOKCTRL
1711
1712#if wxUSE_BOOKCTRL
1713
1714wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1715 : m_bookctrl(bookctrl)
1716{
1717 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1718}
1719
1720void wxBookCtrlSizer::RecalcSizes()
1721{
1722 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1723}
1724
1725wxSize wxBookCtrlSizer::CalcMin()
1726{
1727 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1728
1729 sizeBorder.x += 5;
1730 sizeBorder.y += 5;
1731
1732 if ( m_bookctrl->GetPageCount() == 0 )
1733 {
1734 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1735 }
1736
1737 int maxX = 0;
1738 int maxY = 0;
1739
1740 wxWindowList::compatibility_iterator
1741 node = m_bookctrl->GetChildren().GetFirst();
1742 while (node)
1743 {
1744 wxWindow *item = node->GetData();
1745 wxSizer *itemsizer = item->GetSizer();
1746
1747 if (itemsizer)
1748 {
1749 wxSize subsize( itemsizer->CalcMin() );
1750
1751 if (subsize.x > maxX)
1752 maxX = subsize.x;
1753 if (subsize.y > maxY)
1754 maxY = subsize.y;
1755 }
1756
1757 node = node->GetNext();
1758 }
1759
1760 return wxSize( maxX, maxY ) + sizeBorder;
1761}
1762
1763#if wxUSE_NOTEBOOK
1764
1765wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1766{
1767 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
1768 m_bookctrl = nb;
1769}
1770
1771#endif // wxUSE_NOTEBOOOK
1772#endif // wxUSE_BOOKCTRL
1773
1774#endif // WXWIN_COMPATIBILITY_2_4