]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
otherwise all runloop dependent callbacks cannot work outside of the main thread
[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 // the size of the window may change during run-time, we should
199 // use the current minimal size
200 m_minSize = m_window->GetAdjustedBestSize();
201 }
202
203 ret = m_minSize;
204 }
205
206 if (m_flag & wxWEST)
207 ret.x += m_border;
208 if (m_flag & wxEAST)
209 ret.x += m_border;
210 if (m_flag & wxNORTH)
211 ret.y += m_border;
212 if (m_flag & wxSOUTH)
213 ret.y += m_border;
214
215 return ret;
216 }
217
218 void wxSizerItem::SetDimension( wxPoint pos, wxSize size )
219 {
220 if (m_flag & wxSHAPED)
221 {
222 // adjust aspect ratio
223 int rwidth = (int) (size.y * m_ratio);
224 if (rwidth > size.x)
225 {
226 // fit horizontally
227 int rheight = (int) (size.x / m_ratio);
228 // add vertical space
229 if (m_flag & wxALIGN_CENTER_VERTICAL)
230 pos.y += (size.y - rheight) / 2;
231 else if (m_flag & wxALIGN_BOTTOM)
232 pos.y += (size.y - rheight);
233 // use reduced dimensions
234 size.y =rheight;
235 }
236 else if (rwidth < size.x)
237 {
238 // add horizontal space
239 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
240 pos.x += (size.x - rwidth) / 2;
241 else if (m_flag & wxALIGN_RIGHT)
242 pos.x += (size.x - rwidth);
243 size.x = rwidth;
244 }
245 }
246
247 // This is what GetPosition() returns. Since we calculate
248 // borders afterwards, GetPosition() will be the left/top
249 // corner of the surrounding border.
250 m_pos = pos;
251
252 if (m_flag & wxWEST)
253 {
254 pos.x += m_border;
255 size.x -= m_border;
256 }
257 if (m_flag & wxEAST)
258 {
259 size.x -= m_border;
260 }
261 if (m_flag & wxNORTH)
262 {
263 pos.y += m_border;
264 size.y -= m_border;
265 }
266 if (m_flag & wxSOUTH)
267 {
268 size.y -= m_border;
269 }
270
271 if (IsSizer())
272 m_sizer->SetDimension( pos.x, pos.y, size.x, size.y );
273
274 if (IsWindow())
275 m_window->SetSize( pos.x, pos.y, size.x, size.y, wxSIZE_ALLOW_MINUS_ONE );
276
277 m_size = size;
278 }
279
280 void wxSizerItem::DeleteWindows()
281 {
282 if (m_window)
283 {
284 m_window->Destroy();
285 m_window = NULL;
286 }
287
288 if (m_sizer)
289 m_sizer->DeleteWindows();
290 }
291
292 bool wxSizerItem::IsWindow() const
293 {
294 return (m_window != NULL);
295 }
296
297 bool wxSizerItem::IsSizer() const
298 {
299 return (m_sizer != NULL);
300 }
301
302 bool wxSizerItem::IsSpacer() const
303 {
304 return (m_window == NULL) && (m_sizer == NULL);
305 }
306
307 void wxSizerItem::Show( bool show )
308 {
309 m_show = show;
310
311 if( IsWindow() )
312 m_window->Show( show );
313 else if( IsSizer() )
314 m_sizer->ShowItems( show );
315
316 // ... nothing else to do to hide/show spacers
317 }
318
319 void wxSizerItem::SetOption( int option )
320 {
321 SetProportion( option );
322 }
323
324 int wxSizerItem::GetOption() const
325 {
326 return GetProportion();
327 }
328
329
330 //---------------------------------------------------------------------------
331 // wxSizer
332 //---------------------------------------------------------------------------
333
334 wxSizer::wxSizer()
335 : m_minSize( wxSize( 0, 0 ) )
336 {
337 }
338
339 wxSizer::~wxSizer()
340 {
341 WX_CLEAR_LIST(wxSizerItemList, m_children);
342 }
343
344 void wxSizer::Add( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
345 {
346 m_children.Append( new wxSizerItem( window, proportion, flag, border, userData ) );
347 window->SetContainingSizer( this );
348 }
349
350 void wxSizer::Add( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
351 {
352 m_children.Append( new wxSizerItem( sizer, proportion, flag, border, userData ) );
353 }
354
355 void wxSizer::Add( int width, int height, int proportion, int flag, int border, wxObject* userData )
356 {
357 m_children.Append( new wxSizerItem( width, height, proportion, flag, border, userData ) );
358 }
359
360 void wxSizer::Add( wxSizerItem *item )
361 {
362 m_children.Append( item );
363
364 if( item->GetWindow() )
365 item->GetWindow()->SetContainingSizer( this );
366 }
367
368 void wxSizer::Prepend( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
369 {
370 m_children.Insert( new wxSizerItem( window, proportion, flag, border, userData ) );
371 window->SetContainingSizer( this );
372 }
373
374 void wxSizer::Prepend( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
375 {
376 m_children.Insert( new wxSizerItem( sizer, proportion, flag, border, userData ) );
377 }
378
379 void wxSizer::Prepend( int width, int height, int proportion, int flag, int border, wxObject* userData )
380 {
381 m_children.Insert( new wxSizerItem( width, height, proportion, flag, border, userData ) );
382 }
383
384 void wxSizer::Prepend( wxSizerItem *item )
385 {
386 m_children.Insert( item );
387
388 if( item->GetWindow() )
389 item->GetWindow()->SetContainingSizer( this );
390 }
391
392 void wxSizer::Insert( size_t index,
393 wxWindow *window,
394 int proportion,
395 int flag,
396 int border,
397 wxObject* userData )
398 {
399 m_children.Insert( index,
400 new wxSizerItem( window, proportion, flag, border, userData ) );
401 window->SetContainingSizer( this );
402 }
403
404 void wxSizer::Insert( size_t index,
405 wxSizer *sizer,
406 int proportion,
407 int flag,
408 int border,
409 wxObject* userData )
410 {
411 m_children.Insert( index,
412 new wxSizerItem( sizer, proportion, flag, border, userData ) );
413 }
414
415 void wxSizer::Insert( size_t index,
416 int width,
417 int height,
418 int proportion,
419 int flag,
420 int border,
421 wxObject* userData )
422 {
423 m_children.Insert( index,
424 new wxSizerItem( width, height, proportion, flag, border, userData ) );
425 }
426
427 void wxSizer::Insert( size_t index, wxSizerItem *item )
428 {
429 m_children.Insert( index, item );
430
431 if( item->GetWindow() )
432 item->GetWindow()->SetContainingSizer( this );
433 }
434
435 bool wxSizer::Remove( wxWindow *window )
436 {
437 return Detach( window );
438 }
439
440 bool wxSizer::Remove( wxSizer *sizer )
441 {
442 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
443
444 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
445 while (node)
446 {
447 wxSizerItem *item = node->GetData();
448
449 if (item->GetSizer() == sizer)
450 {
451 delete item;
452 m_children.Erase( node );
453 return true;
454 }
455
456 node = node->GetNext();
457 }
458
459 return false;
460 }
461
462 bool wxSizer::Remove( int index )
463 {
464 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
465 false,
466 _T("Remove index is out of range") );
467
468 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
469
470 wxCHECK_MSG( node, false, _T("Failed to find child node") );
471
472 wxSizerItem *item = node->GetData();
473
474 if( item->IsWindow() )
475 item->GetWindow()->SetContainingSizer( NULL );
476
477 delete item;
478 m_children.Erase( node );
479 return true;
480 }
481
482 bool wxSizer::Detach( wxSizer *sizer )
483 {
484 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
485
486 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
487 while (node)
488 {
489 wxSizerItem *item = node->GetData();
490
491 if (item->GetSizer() == sizer)
492 {
493 item->DetachSizer();
494 delete item;
495 m_children.Erase( node );
496 return true;
497 }
498 node = node->GetNext();
499 }
500
501 return false;
502 }
503
504 bool wxSizer::Detach( wxWindow *window )
505 {
506 wxASSERT_MSG( window, _T("Detaching NULL window") );
507
508 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
509 while (node)
510 {
511 wxSizerItem *item = node->GetData();
512
513 if (item->GetWindow() == window)
514 {
515 item->GetWindow()->SetContainingSizer( NULL );
516 delete item;
517 m_children.Erase( node );
518 return true;
519 }
520 node = node->GetNext();
521 }
522
523 return false;
524 }
525
526 bool wxSizer::Detach( int index )
527 {
528 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
529 false,
530 _T("Detach index is out of range") );
531
532 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
533
534 wxCHECK_MSG( node, false, _T("Failed to find child node") );
535
536 wxSizerItem *item = node->GetData();
537
538 if( item->IsSizer() )
539 item->DetachSizer();
540 else if( item->IsWindow() )
541 item->GetWindow()->SetContainingSizer( NULL );
542
543 delete item;
544 m_children.Erase( node );
545 return true;
546 }
547
548 void wxSizer::Clear( bool delete_windows )
549 {
550 // First clear the ContainingSizer pointers
551 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
552 while (node)
553 {
554 wxSizerItem *item = node->GetData();
555
556 if (item->IsWindow())
557 item->GetWindow()->SetContainingSizer( NULL );
558 node = node->GetNext();
559 }
560
561 // Destroy the windows if needed
562 if (delete_windows)
563 DeleteWindows();
564
565 // Now empty the list
566 WX_CLEAR_LIST(wxSizerItemList, m_children);
567 }
568
569 void wxSizer::DeleteWindows()
570 {
571 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
572 while (node)
573 {
574 wxSizerItem *item = node->GetData();
575
576 item->DeleteWindows();
577 node = node->GetNext();
578 }
579 }
580
581 wxSize wxSizer::Fit( wxWindow *window )
582 {
583 wxSize size(window->IsTopLevel() ? FitSize(window)
584 : GetMinWindowSize(window));
585
586 window->SetSize( size );
587
588 return size;
589 }
590
591 void wxSizer::FitInside( wxWindow *window )
592 {
593 wxSize size;
594 if (window->IsTopLevel())
595 size = VirtualFitSize( window );
596 else
597 size = GetMinClientSize( window );
598
599 window->SetVirtualSize( size );
600 }
601
602 void wxSizer::Layout()
603 {
604 CalcMin();
605 RecalcSizes();
606 }
607
608 void wxSizer::SetSizeHints( wxWindow *window )
609 {
610 // Preserve the window's max size hints, but set the
611 // lower bound according to the sizer calculations.
612
613 wxSize size = Fit( window );
614
615 window->SetSizeHints( size.x,
616 size.y,
617 window->GetMaxWidth(),
618 window->GetMaxHeight() );
619 }
620
621 void wxSizer::SetVirtualSizeHints( wxWindow *window )
622 {
623 // Preserve the window's max size hints, but set the
624 // lower bound according to the sizer calculations.
625
626 FitInside( window );
627 wxSize size( window->GetVirtualSize() );
628 window->SetVirtualSizeHints( size.x,
629 size.y,
630 window->GetMaxWidth(),
631 window->GetMaxHeight() );
632 }
633
634 wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
635 {
636 return window->GetMaxSize();
637 }
638
639 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
640 {
641 wxSize minSize( GetMinSize() );
642 wxSize size( window->GetSize() );
643 wxSize client_size( window->GetClientSize() );
644
645 return wxSize( minSize.x+size.x-client_size.x,
646 minSize.y+size.y-client_size.y );
647 }
648
649 // TODO on mac we need a function that determines how much free space this
650 // min size contains, in order to make sure that we have 20 pixels of free
651 // space around the controls
652
653 // Return a window size that will fit within the screens dimensions
654 wxSize wxSizer::FitSize( wxWindow *window )
655 {
656 wxSize size = GetMinWindowSize( window );
657 wxSize sizeMax = GetMaxWindowSize( window );
658
659 // Limit the size if sizeMax != wxDefaultSize
660
661 if ( size.x > sizeMax.x && sizeMax.x != -1 )
662 size.x = sizeMax.x;
663 if ( size.y > sizeMax.y && sizeMax.y != -1 )
664 size.y = sizeMax.y;
665
666 return size;
667 }
668
669 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
670 {
671 wxSize maxSize( window->GetMaxSize() );
672
673 if( maxSize != wxDefaultSize )
674 {
675 wxSize size( window->GetSize() );
676 wxSize client_size( window->GetClientSize() );
677
678 return wxSize( maxSize.x + client_size.x - size.x,
679 maxSize.y + client_size.y - size.y );
680 }
681 else
682 return wxDefaultSize;
683 }
684
685 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
686 {
687 return GetMinSize(); // Already returns client size.
688 }
689
690 wxSize wxSizer::VirtualFitSize( wxWindow *window )
691 {
692 wxSize size = GetMinClientSize( window );
693 wxSize sizeMax = GetMaxClientSize( window );
694
695 // Limit the size if sizeMax != wxDefaultSize
696
697 if ( size.x > sizeMax.x && sizeMax.x != -1 )
698 size.x = sizeMax.x;
699 if ( size.y > sizeMax.y && sizeMax.y != -1 )
700 size.y = sizeMax.y;
701
702 return size;
703 }
704
705 void wxSizer::SetDimension( int x, int y, int width, int height )
706 {
707 m_position.x = x;
708 m_position.y = y;
709 m_size.x = width;
710 m_size.y = height;
711 Layout();
712 }
713
714 wxSize wxSizer::GetMinSize()
715 {
716 wxSize ret( CalcMin() );
717 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
718 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
719 return ret;
720 }
721
722 void wxSizer::DoSetMinSize( int width, int height )
723 {
724 m_minSize.x = width;
725 m_minSize.y = height;
726 }
727
728 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
729 {
730 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
731
732 // Is it our immediate child?
733
734 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
735 while (node)
736 {
737 wxSizerItem *item = node->GetData();
738
739 if (item->GetWindow() == window)
740 {
741 item->SetMinSize( width, height );
742 return true;
743 }
744 node = node->GetNext();
745 }
746
747 // No? Search any subsizers we own then
748
749 node = m_children.GetFirst();
750 while (node)
751 {
752 wxSizerItem *item = node->GetData();
753
754 if ( item->GetSizer() &&
755 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
756 {
757 // A child sizer found the requested windw, exit.
758 return true;
759 }
760 node = node->GetNext();
761 }
762
763 return false;
764 }
765
766 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
767 {
768 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
769
770 // Is it our immediate child?
771
772 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
773 while (node)
774 {
775 wxSizerItem *item = node->GetData();
776
777 if (item->GetSizer() == sizer)
778 {
779 item->GetSizer()->DoSetMinSize( width, height );
780 return true;
781 }
782 node = node->GetNext();
783 }
784
785 // No? Search any subsizers we own then
786
787 node = m_children.GetFirst();
788 while (node)
789 {
790 wxSizerItem *item = node->GetData();
791
792 if ( item->GetSizer() &&
793 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
794 {
795 // A child found the requested sizer, exit.
796 return true;
797 }
798 node = node->GetNext();
799 }
800
801 return false;
802 }
803
804 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
805 {
806 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
807
808 wxCHECK_MSG( node, false, _T("Failed to find child node") );
809
810 wxSizerItem *item = node->GetData();
811
812 if (item->GetSizer())
813 {
814 // Sizers contains the minimal size in them, if not calculated ...
815 item->GetSizer()->DoSetMinSize( width, height );
816 }
817 else
818 {
819 // ... but the minimal size of spacers and windows in stored in them
820 item->SetMinSize( width, height );
821 }
822
823 return true;
824 }
825
826 void wxSizer::Show( wxWindow *window, bool show )
827 {
828 wxASSERT_MSG( window, _T("Show for NULL window") );
829
830 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
831 while (node)
832 {
833 wxSizerItem *item = node->GetData();
834
835 if (item->GetWindow() == window)
836 {
837 item->Show( show );
838 break;
839 }
840 node = node->GetNext();
841 }
842 }
843
844 void wxSizer::Show( wxSizer *sizer, bool show )
845 {
846 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
847
848 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
849 while (node)
850 {
851 wxSizerItem *item = node->GetData();
852
853 if (item->GetSizer() == sizer)
854 {
855 item->Show( show );
856 break;
857 }
858 node = node->GetNext();
859 }
860 }
861
862 void wxSizer::Show( size_t index, bool show )
863 {
864 wxCHECK_RET( index < m_children.GetCount(),
865 _T("Show index is out of range") );
866
867 m_children.Item( index )->GetData()->Show( show );
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->CalcMin() );
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 wxSize minsz( CalcMin() );
1102
1103 AdjustForGrowables(sz, minsz, nrows, ncols);
1104
1105 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1106
1107 int x = pt.x;
1108 for (int c = 0; c < ncols; c++)
1109 {
1110 int y = pt.y;
1111 for (int r = 0; r < nrows; r++)
1112 {
1113 int i = r * ncols + c;
1114 if (i < nitems)
1115 {
1116 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1117
1118 wxASSERT_MSG( node, _T("Failed to find node") );
1119
1120 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1121 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1122
1123 SetItemBounds( node->GetData(), x, y, w, h);
1124 }
1125 y = y + m_rowHeights[r] + m_vgap;
1126 }
1127 x = x + m_colWidths[c] + m_hgap;
1128 }
1129 }
1130
1131 wxSize wxFlexGridSizer::CalcMin()
1132 {
1133 int nrows,
1134 ncols;
1135 size_t i, s;
1136
1137 // Number of rows/columns can change as items are added or removed.
1138 if ( !CalcRowsCols(nrows, ncols) )
1139 return wxSize(10, 10);
1140
1141 m_rowHeights.SetCount(nrows);
1142 m_colWidths.SetCount(ncols);
1143
1144 // We have to recalcuate the sizes in case the item minimum size has
1145 // changed since the previous layout, or the item has been hidden using
1146 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1147 // dimension of the row/column will be -1, indicating that the column
1148 // itself is hidden.
1149 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1150 m_rowHeights[ i ] = -1;
1151 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1152 m_colWidths[ i ] = -1;
1153
1154 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1155
1156 i = 0;
1157 while (node)
1158 {
1159 wxSizerItem *item = node->GetData();
1160 if ( item->IsShown() )
1161 {
1162 wxSize sz( item->CalcMin() );
1163 int row = i / ncols;
1164 int col = i % ncols;
1165
1166 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1167 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1168 }
1169
1170 node = node->GetNext();
1171 i++;
1172 }
1173
1174 AdjustForFlexDirection();
1175
1176 // Sum total minimum size, including gaps between rows/columns.
1177 // -1 is used as a magic number meaning empty column.
1178 int width = 0;
1179 for (int col = 0; col < ncols; col++)
1180 if ( m_colWidths[ col ] != -1 )
1181 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1182
1183 int height = 0;
1184 for (int row = 0; row < nrows; row++)
1185 if ( m_rowHeights[ row ] != -1 )
1186 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1187
1188 return wxSize( width, height );
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->CalcMin() );
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( wxSize( 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( wxSize(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 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1455 while (node)
1456 {
1457 wxSizerItem *item = node->GetData();
1458
1459 if (item->IsShown() && item->GetProportion() != 0)
1460 m_stretchable += item->GetProportion();
1461
1462 node = node->GetNext();
1463 }
1464
1465 // Total minimum size (width or height) of sizer
1466 int maxMinSize = 0;
1467
1468 node = m_children.GetFirst();
1469 while (node)
1470 {
1471 wxSizerItem *item = node->GetData();
1472
1473 if (item->IsShown() && item->GetProportion() != 0)
1474 {
1475 int stretch = item->GetProportion();
1476 wxSize size( item->CalcMin() );
1477 int minSize;
1478
1479 // Integer division rounded up is (a + b - 1) / b
1480 // Round up needed in order to guarantee that all
1481 // all items will have size not less then their min size
1482 if (m_orient == wxHORIZONTAL)
1483 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1484 else
1485 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1486
1487 if (minSize > maxMinSize)
1488 maxMinSize = minSize;
1489 }
1490 node = node->GetNext();
1491 }
1492
1493 // Calculate overall minimum size
1494 node = m_children.GetFirst();
1495 while (node)
1496 {
1497 wxSizerItem *item = node->GetData();
1498
1499 if (item->IsShown())
1500 {
1501 wxSize size( item->CalcMin() );
1502 if (item->GetProportion() != 0)
1503 {
1504 if (m_orient == wxHORIZONTAL)
1505 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1506 else
1507 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1508 }
1509 else
1510 {
1511 if (m_orient == wxVERTICAL)
1512 {
1513 m_fixedHeight += size.y;
1514 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1515 }
1516 else
1517 {
1518 m_fixedWidth += size.x;
1519 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1520 }
1521 }
1522
1523 if (m_orient == wxHORIZONTAL)
1524 {
1525 m_minWidth += size.x;
1526 m_minHeight = wxMax( m_minHeight, size.y );
1527 }
1528 else
1529 {
1530 m_minHeight += size.y;
1531 m_minWidth = wxMax( m_minWidth, size.x );
1532 }
1533 }
1534 node = node->GetNext();
1535 }
1536
1537 return wxSize( m_minWidth, m_minHeight );
1538 }
1539
1540 //---------------------------------------------------------------------------
1541 // wxStaticBoxSizer
1542 //---------------------------------------------------------------------------
1543
1544 #if wxUSE_STATBOX
1545
1546 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1547 : wxBoxSizer( orient )
1548 , m_staticBox( box )
1549 {
1550 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1551 }
1552
1553 static void GetStaticBoxBorders( wxStaticBox *box,
1554 int *borderTop,
1555 int *borderOther)
1556 {
1557 // this has to be done platform by platform as there is no way to
1558 // guess the thickness of a wxStaticBox border
1559 #ifdef __WXCOCOA__
1560 box->GetBordersForSizer(borderTop,borderOther);
1561 #elif defined(__WXMAC__)
1562
1563 static int extraTop = -1; // Uninitted
1564 static int other = 5;
1565
1566 if ( extraTop == -1 )
1567 {
1568 // The minimal border used for the top. Later on the staticbox'
1569 // font height is added to this.
1570 extraTop = 0;
1571
1572 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1573 {
1574 // As indicated by the HIG, Panther needs an extra border of 11
1575 // pixels (otherwise overlapping occurs at the top). The "other"
1576 // border has to be 11.
1577 extraTop = 11;
1578 other = 11;
1579 }
1580
1581 }
1582
1583 *borderTop = extraTop + box->GetCharHeight();
1584 *borderOther = other;
1585
1586 #else
1587 #ifdef __WXGTK__
1588 if ( box->GetLabel().IsEmpty() )
1589 *borderTop = 5;
1590 else
1591 #endif // __WXGTK__
1592 *borderTop = box->GetCharHeight();
1593
1594 *borderOther = 5;
1595 #endif // __WXCOCOA__
1596 }
1597
1598 void wxStaticBoxSizer::RecalcSizes()
1599 {
1600 int top_border, other_border;
1601 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1602
1603 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1604
1605 wxPoint old_pos( m_position );
1606 m_position.x += other_border;
1607 m_position.y += top_border;
1608 wxSize old_size( m_size );
1609 m_size.x -= 2*other_border;
1610 m_size.y -= top_border + other_border;
1611
1612 wxBoxSizer::RecalcSizes();
1613
1614 m_position = old_pos;
1615 m_size = old_size;
1616 }
1617
1618 wxSize wxStaticBoxSizer::CalcMin()
1619 {
1620 int top_border, other_border;
1621 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1622
1623 wxSize ret( wxBoxSizer::CalcMin() );
1624 ret.x += 2*other_border;
1625 ret.y += other_border + top_border;
1626
1627 return ret;
1628 }
1629
1630 void wxStaticBoxSizer::ShowItems( bool show )
1631 {
1632 m_staticBox->Show( show );
1633 wxBoxSizer::ShowItems( show );
1634 }
1635
1636 #endif // wxUSE_STATBOX
1637
1638 // ----------------------------------------------------------------------------
1639 // wxNotebookSizer
1640 // ----------------------------------------------------------------------------
1641
1642 #if wxUSE_BOOKCTRL
1643
1644 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1645 : m_bookctrl(bookctrl)
1646 {
1647 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1648 }
1649
1650 void wxBookCtrlSizer::RecalcSizes()
1651 {
1652 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1653 }
1654
1655 wxSize wxBookCtrlSizer::CalcMin()
1656 {
1657 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1658
1659 sizeBorder.x += 5;
1660 sizeBorder.y += 5;
1661
1662 if ( m_bookctrl->GetPageCount() == 0 )
1663 {
1664 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1665 }
1666
1667 int maxX = 0;
1668 int maxY = 0;
1669
1670 wxWindowList::compatibility_iterator
1671 node = m_bookctrl->GetChildren().GetFirst();
1672 while (node)
1673 {
1674 wxWindow *item = node->GetData();
1675 wxSizer *itemsizer = item->GetSizer();
1676
1677 if (itemsizer)
1678 {
1679 wxSize subsize( itemsizer->CalcMin() );
1680
1681 if (subsize.x > maxX)
1682 maxX = subsize.x;
1683 if (subsize.y > maxY)
1684 maxY = subsize.y;
1685 }
1686
1687 node = node->GetNext();
1688 }
1689
1690 return wxSize( maxX, maxY ) + sizeBorder;
1691 }
1692
1693
1694 #if wxUSE_NOTEBOOK
1695
1696 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1697 : wxBookCtrlSizer(nb)
1698 {
1699 }
1700
1701 #endif // wxUSE_NOTEBOOOK
1702 #endif // wxUSE_BOOKCTRL
1703