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