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