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