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