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