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