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