]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
Added wxFIXED_SIZE.
[wxWidgets.git] / src / common / sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sizer.cpp
3 // Purpose: provide new wxSizer class for layout
4 // Author: Robert Roebling and Robin Dunn, contributions by
5 // Dirk Holtwick, Ron Lee
6 // Modified by: Ron Lee
7 // Created:
8 // RCS-ID: $Id$
9 // Copyright: (c) Robin Dunn, Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
14 #pragma implementation "sizer.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #include "wx/sizer.h"
25 #include "wx/utils.h"
26 #include "wx/statbox.h"
27 #include "wx/notebook.h"
28 #include "wx/listimpl.cpp"
29
30 #ifdef __WXMAC__
31 # include "wx/mac/uma.h"
32 #endif
33
34 //---------------------------------------------------------------------------
35
36 IMPLEMENT_CLASS(wxSizerItem, wxObject)
37 IMPLEMENT_CLASS(wxSizer, wxObject)
38 IMPLEMENT_CLASS(wxGridSizer, wxSizer)
39 IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
40 IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
41 #if wxUSE_STATBOX
42 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
43 #endif
44 #if wxUSE_BOOKCTRL
45 IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
46 #if wxUSE_NOTEBOOK
47 IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
48 #endif // wxUSE_NOTEBOOK
49 #endif // wxUSE_BOOKCTRL
50
51 WX_DEFINE_EXPORTED_LIST( wxSizerItemList );
52
53 /*
54 TODO PROPERTIES
55 sizeritem
56 object
57 object_ref
58 minsize
59 option
60 flag
61 border
62 spacer
63 option
64 flag
65 borfder
66 boxsizer
67 orient
68 staticboxsizer
69 orient
70 label
71 gridsizer
72 rows
73 cols
74 vgap
75 hgap
76 flexgridsizer
77 rows
78 cols
79 vgap
80 hgap
81 growablerows
82 growablecols
83 minsize
84 */
85 //---------------------------------------------------------------------------
86 // wxSizerItem
87 //---------------------------------------------------------------------------
88
89 wxSizerItem::wxSizerItem( int width, int height, int proportion, int flag, int border, wxObject* userData )
90 : m_window( NULL )
91 , m_sizer( NULL )
92 , m_size( wxSize( width, height ) ) // size is set directly
93 , m_minSize( m_size ) // minimal size is the initial size
94 , m_proportion( proportion )
95 , m_border( border )
96 , m_flag( flag )
97 , m_show( true )
98 , m_userData( userData )
99 {
100 SetRatio( m_size );
101 }
102
103 wxSizerItem::wxSizerItem( wxWindow *window, int proportion, int flag, int border, wxObject* userData )
104 : m_window( window )
105 , m_sizer( NULL )
106 , m_minSize( window->GetSize() ) // minimal size is the initial size
107 , m_proportion( proportion )
108 , m_border( border )
109 , m_flag( flag )
110 , m_show( true )
111 , m_userData( userData )
112 {
113 // aspect ratio calculated from initial size
114 SetRatio( m_minSize );
115
116 // m_size is calculated later
117 }
118
119 wxSizerItem::wxSizerItem( wxSizer *sizer, int proportion, int flag, int border, wxObject* userData )
120 : m_window( NULL )
121 , m_sizer( sizer )
122 , m_proportion( proportion )
123 , m_border( border )
124 , m_flag( flag )
125 , m_show( true )
126 , m_ratio( 0.0 )
127 , m_userData( userData )
128 {
129 // m_minSize is calculated later
130 // m_size is calculated later
131 }
132
133 wxSizerItem::wxSizerItem()
134 : m_window( NULL )
135 , m_sizer( NULL )
136 , m_proportion( 0 )
137 , m_border( 0 )
138 , m_flag( 0 )
139 , m_show( true )
140 , m_ratio( 0.0 )
141 , m_userData( NULL )
142 {
143 }
144
145 wxSizerItem::~wxSizerItem()
146 {
147 delete m_userData;
148
149 if ( m_window )
150 {
151 m_window->SetContainingSizer(NULL);
152 }
153 else // we must be a sizer
154 {
155 delete m_sizer;
156 }
157 }
158
159
160 wxSize wxSizerItem::GetSize() const
161 {
162 wxSize ret;
163 if (IsSizer())
164 ret = m_sizer->GetSize();
165 else
166 if (IsWindow())
167 ret = m_window->GetSize();
168 else ret = m_size;
169
170 if (m_flag & wxWEST)
171 ret.x += m_border;
172 if (m_flag & wxEAST)
173 ret.x += m_border;
174 if (m_flag & wxNORTH)
175 ret.y += m_border;
176 if (m_flag & wxSOUTH)
177 ret.y += m_border;
178
179 return ret;
180 }
181
182 wxSize wxSizerItem::CalcMin()
183 {
184 wxSize ret;
185 if (IsSizer())
186 {
187 ret = m_sizer->GetMinSize();
188
189 // if we have to preserve aspect ratio _AND_ this is
190 // the first-time calculation, consider ret to be initial size
191 if ((m_flag & wxSHAPED) && !m_ratio)
192 SetRatio(ret);
193 }
194 else
195 {
196 if ( IsWindow() && !(m_flag & wxFIXED_SIZE) )
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 item->GetWindow()->SetSizeHints(width, height);
740 return true;
741 }
742 node = node->GetNext();
743 }
744
745 // No? Search any subsizers we own then
746
747 node = m_children.GetFirst();
748 while (node)
749 {
750 wxSizerItem *item = node->GetData();
751
752 if ( item->GetSizer() &&
753 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
754 {
755 // A child sizer found the requested windw, exit.
756 return true;
757 }
758 node = node->GetNext();
759 }
760
761 return false;
762 }
763
764 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
765 {
766 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
767
768 // Is it our immediate child?
769
770 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
771 while (node)
772 {
773 wxSizerItem *item = node->GetData();
774
775 if (item->GetSizer() == sizer)
776 {
777 item->GetSizer()->DoSetMinSize( width, height );
778 return true;
779 }
780 node = node->GetNext();
781 }
782
783 // No? Search any subsizers we own then
784
785 node = m_children.GetFirst();
786 while (node)
787 {
788 wxSizerItem *item = node->GetData();
789
790 if ( item->GetSizer() &&
791 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
792 {
793 // A child found the requested sizer, exit.
794 return true;
795 }
796 node = node->GetNext();
797 }
798
799 return false;
800 }
801
802 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
803 {
804 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
805
806 wxCHECK_MSG( node, false, _T("Failed to find child node") );
807
808 wxSizerItem *item = node->GetData();
809
810 if (item->GetSizer())
811 {
812 // Sizers contains the minimal size in them, if not calculated ...
813 item->GetSizer()->DoSetMinSize( width, height );
814 }
815 else
816 {
817 // ... but the minimal size of spacers and windows in stored in them
818 item->SetInitSize( width, height );
819 if (item->GetWindow())
820 item->GetWindow()->SetSizeHints(width, height);
821 }
822
823 return true;
824 }
825
826 void wxSizer::Show( wxWindow *window, bool show )
827 {
828 wxASSERT_MSG( window, _T("Show for NULL window") );
829
830 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
831 while (node)
832 {
833 wxSizerItem *item = node->GetData();
834
835 if (item->GetWindow() == window)
836 {
837 item->Show( show );
838 break;
839 }
840 node = node->GetNext();
841 }
842 }
843
844 void wxSizer::Show( wxSizer *sizer, bool show )
845 {
846 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
847
848 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
849 while (node)
850 {
851 wxSizerItem *item = node->GetData();
852
853 if (item->GetSizer() == sizer)
854 {
855 item->Show( show );
856 break;
857 }
858 node = node->GetNext();
859 }
860 }
861
862 void wxSizer::Show( size_t index, bool show )
863 {
864 wxCHECK_RET( index < m_children.GetCount(),
865 _T("Show index is out of range") );
866
867 m_children.Item( index )->GetData()->Show( show );
868 }
869
870 void wxSizer::ShowItems( bool show )
871 {
872 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
873 while (node)
874 {
875 node->GetData()->Show( show );
876 node = node->GetNext();
877 }
878 }
879
880 bool wxSizer::IsShown( wxWindow *window ) const
881 {
882 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
883 while (node)
884 {
885 wxSizerItem *item = node->GetData();
886
887 if (item->GetWindow() == window)
888 {
889 return item->IsShown();
890 }
891 node = node->GetNext();
892 }
893
894 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
895
896 return false;
897 }
898
899 bool wxSizer::IsShown( wxSizer *sizer ) const
900 {
901 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
902 while (node)
903 {
904 wxSizerItem *item = node->GetData();
905
906 if (item->GetSizer() == sizer)
907 {
908 return item->IsShown();
909 }
910 node = node->GetNext();
911 }
912
913 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
914
915 return false;
916 }
917
918 bool wxSizer::IsShown( size_t index ) const
919 {
920 wxCHECK_MSG( index < m_children.GetCount(),
921 false,
922 _T("IsShown index is out of range") );
923
924 return m_children.Item( index )->GetData()->IsShown();
925 }
926
927
928 //---------------------------------------------------------------------------
929 // wxGridSizer
930 //---------------------------------------------------------------------------
931
932 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
933 : m_rows( rows )
934 , m_cols( cols )
935 , m_vgap( vgap )
936 , m_hgap( hgap )
937 {
938 if (m_rows == 0 && m_cols == 0)
939 m_rows = 1;
940 }
941
942 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
943 : m_rows( 0 )
944 , m_cols( cols )
945 , m_vgap( vgap )
946 , m_hgap( hgap )
947 {
948 if (m_rows == 0 && m_cols == 0)
949 m_rows = 1;
950 }
951
952 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
953 {
954 int nitems = m_children.GetCount();
955 if ( nitems)
956 {
957 if ( m_cols )
958 {
959 ncols = m_cols;
960 nrows = (nitems + m_cols - 1) / m_cols;
961 }
962 else if ( m_rows )
963 {
964 ncols = (nitems + m_rows - 1) / m_rows;
965 nrows = m_rows;
966 }
967 else // 0 columns, 0 rows?
968 {
969 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
970
971 nrows = ncols = 0;
972 }
973 }
974
975 return nitems;
976 }
977
978 void wxGridSizer::RecalcSizes()
979 {
980 int nitems, nrows, ncols;
981 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
982 return;
983
984 wxSize sz( GetSize() );
985 wxPoint pt( GetPosition() );
986
987 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
988 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
989
990 int x = pt.x;
991 for (int c = 0; c < ncols; c++)
992 {
993 int y = pt.y;
994 for (int r = 0; r < nrows; r++)
995 {
996 int i = r * ncols + c;
997 if (i < nitems)
998 {
999 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1000
1001 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
1002
1003 SetItemBounds( node->GetData(), x, y, w, h);
1004 }
1005 y = y + h + m_vgap;
1006 }
1007 x = x + w + m_hgap;
1008 }
1009 }
1010
1011 wxSize wxGridSizer::CalcMin()
1012 {
1013 int nrows, ncols;
1014 if ( CalcRowsCols(nrows, ncols) == 0 )
1015 return wxSize(10, 10);
1016
1017 // Find the max width and height for any component
1018 int w = 0;
1019 int h = 0;
1020
1021 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1022 while (node)
1023 {
1024 wxSizerItem *item = node->GetData();
1025 wxSize sz( item->CalcMin() );
1026
1027 w = wxMax( w, sz.x );
1028 h = wxMax( h, sz.y );
1029
1030 node = node->GetNext();
1031 }
1032
1033 return wxSize( ncols * w + (ncols-1) * m_hgap,
1034 nrows * h + (nrows-1) * m_vgap );
1035 }
1036
1037 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1038 {
1039 wxPoint pt( x,y );
1040 wxSize sz( item->CalcMin() );
1041 int flag = item->GetFlag();
1042
1043 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1044 {
1045 sz = wxSize(w, h);
1046 }
1047 else
1048 {
1049 if (flag & wxALIGN_CENTER_HORIZONTAL)
1050 {
1051 pt.x = x + (w - sz.x) / 2;
1052 }
1053 else if (flag & wxALIGN_RIGHT)
1054 {
1055 pt.x = x + (w - sz.x);
1056 }
1057
1058 if (flag & wxALIGN_CENTER_VERTICAL)
1059 {
1060 pt.y = y + (h - sz.y) / 2;
1061 }
1062 else if (flag & wxALIGN_BOTTOM)
1063 {
1064 pt.y = y + (h - sz.y);
1065 }
1066 }
1067
1068 item->SetDimension(pt, sz);
1069 }
1070
1071 //---------------------------------------------------------------------------
1072 // wxFlexGridSizer
1073 //---------------------------------------------------------------------------
1074
1075 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1076 : wxGridSizer( rows, cols, vgap, hgap ),
1077 m_flexDirection(wxBOTH),
1078 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1079 {
1080 }
1081
1082 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1083 : wxGridSizer( cols, vgap, hgap ),
1084 m_flexDirection(wxBOTH),
1085 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1086 {
1087 }
1088
1089 wxFlexGridSizer::~wxFlexGridSizer()
1090 {
1091 }
1092
1093 void wxFlexGridSizer::RecalcSizes()
1094 {
1095 int nitems, nrows, ncols;
1096 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1097 return;
1098
1099 wxPoint pt( GetPosition() );
1100 wxSize sz( GetSize() );
1101 wxSize minsz( CalcMin() );
1102
1103 AdjustForGrowables(sz, minsz, nrows, ncols);
1104
1105 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1106
1107 int x = pt.x;
1108 for (int c = 0; c < ncols; c++)
1109 {
1110 int y = pt.y;
1111 for (int r = 0; r < nrows; r++)
1112 {
1113 int i = r * ncols + c;
1114 if (i < nitems)
1115 {
1116 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1117
1118 wxASSERT_MSG( node, _T("Failed to find node") );
1119
1120 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1121 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1122
1123 SetItemBounds( node->GetData(), x, y, w, h);
1124 }
1125 y = y + m_rowHeights[r] + m_vgap;
1126 }
1127 x = x + m_colWidths[c] + m_hgap;
1128 }
1129 }
1130
1131 wxSize wxFlexGridSizer::CalcMin()
1132 {
1133 int nrows,
1134 ncols;
1135 size_t i, s;
1136
1137 // Number of rows/columns can change as items are added or removed.
1138 if ( !CalcRowsCols(nrows, ncols) )
1139 return wxSize(10, 10);
1140
1141 m_rowHeights.SetCount(nrows);
1142 m_colWidths.SetCount(ncols);
1143
1144 // We have to recalcuate the sizes in case the item minimum size has
1145 // changed since the previous layout, or the item has been hidden using
1146 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1147 // dimension of the row/column will be -1, indicating that the column
1148 // itself is hidden.
1149 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1150 m_rowHeights[ i ] = -1;
1151 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1152 m_colWidths[ i ] = -1;
1153
1154 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1155
1156 i = 0;
1157 while (node)
1158 {
1159 wxSizerItem *item = node->GetData();
1160 if ( item->IsShown() )
1161 {
1162 wxSize sz( item->CalcMin() );
1163 int row = i / ncols;
1164 int col = i % ncols;
1165
1166 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1167 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1168 }
1169
1170 node = node->GetNext();
1171 i++;
1172 }
1173
1174 AdjustForFlexDirection();
1175
1176 // Sum total minimum size, including gaps between rows/columns.
1177 // -1 is used as a magic number meaning empty column.
1178 int width = 0;
1179 for (int col = 0; col < ncols; col++)
1180 if ( m_colWidths[ col ] != -1 )
1181 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1182
1183 int height = 0;
1184 for (int row = 0; row < nrows; row++)
1185 if ( m_rowHeights[ row ] != -1 )
1186 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1187
1188 return wxSize( width, height );
1189 }
1190
1191 void wxFlexGridSizer::AdjustForFlexDirection()
1192 {
1193 // the logic in CalcMin works when we resize flexibly in both directions
1194 // but maybe this is not the case
1195 if ( m_flexDirection != wxBOTH )
1196 {
1197 // select the array corresponding to the direction in which we do *not*
1198 // resize flexibly
1199 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1200 : m_rowHeights;
1201
1202 const int count = array.GetCount();
1203
1204 // find the largest value in this array
1205 int n, largest = 0;
1206 for ( n = 0; n < count; ++n )
1207 {
1208 if ( array[n] > largest )
1209 largest = array[n];
1210 }
1211
1212 // and now fill it with the largest value
1213 for ( n = 0; n < count; ++n )
1214 {
1215 array[n] = largest;
1216 }
1217 }
1218 }
1219
1220
1221 void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1222 int nrows, int ncols)
1223 {
1224 // what to do with the rows? by default, resize them proportionally
1225 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1226 {
1227 int sum_proportions = 0;
1228 int growable_space = 0;
1229 int num = 0;
1230 size_t idx;
1231 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1232 {
1233 // Since the number of rows/columns can change as items are
1234 // inserted/deleted, we need to verify at runtime that the
1235 // requested growable rows/columns are still valid.
1236 if (m_growableRows[idx] >= nrows)
1237 continue;
1238
1239 // If all items in a row/column are hidden, that row/column will
1240 // have a dimension of -1. This causes the row/column to be
1241 // hidden completely.
1242 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1243 continue;
1244 sum_proportions += m_growableRowsProportions[idx];
1245 growable_space += m_rowHeights[ m_growableRows[idx] ];
1246 num++;
1247 }
1248
1249 if (num > 0)
1250 {
1251 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1252 {
1253 if (m_growableRows[idx] >= nrows )
1254 continue;
1255 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1256 m_rowHeights[ m_growableRows[idx] ] = 0;
1257 else
1258 {
1259 int delta = (sz.y - minsz.y);
1260 if (sum_proportions == 0)
1261 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1262 else
1263 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1264 m_rowHeights[ m_growableRows[idx] ] = delta;
1265 }
1266 }
1267 }
1268 }
1269 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1270 {
1271 // rounding problem?
1272 for ( int row = 0; row < nrows; ++row )
1273 m_rowHeights[ row ] = sz.y / nrows;
1274 }
1275
1276 // the same logic as above but for the columns
1277 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1278 {
1279 int sum_proportions = 0;
1280 int growable_space = 0;
1281 int num = 0;
1282 size_t idx;
1283 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1284 {
1285 // Since the number of rows/columns can change as items are
1286 // inserted/deleted, we need to verify at runtime that the
1287 // requested growable rows/columns are still valid.
1288 if (m_growableCols[idx] >= ncols)
1289 continue;
1290
1291 // If all items in a row/column are hidden, that row/column will
1292 // have a dimension of -1. This causes the column to be hidden
1293 // completely.
1294 if (m_colWidths[ m_growableCols[idx] ] == -1)
1295 continue;
1296 sum_proportions += m_growableColsProportions[idx];
1297 growable_space += m_colWidths[ m_growableCols[idx] ];
1298 num++;
1299 }
1300
1301 if (num > 0)
1302 {
1303 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1304 {
1305 if (m_growableCols[idx] >= ncols )
1306 continue;
1307 if (m_colWidths[ m_growableCols[idx] ] == -1)
1308 m_colWidths[ m_growableCols[idx] ] = 0;
1309 else
1310 {
1311 int delta = (sz.x - minsz.x);
1312 if (sum_proportions == 0)
1313 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1314 else
1315 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1316 m_colWidths[ m_growableCols[idx] ] = delta;
1317 }
1318 }
1319 }
1320 }
1321 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1322 {
1323 for ( int col=0; col < ncols; ++col )
1324 m_colWidths[ col ] = sz.x / ncols;
1325 }
1326 }
1327
1328
1329 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1330 {
1331 m_growableRows.Add( idx );
1332 m_growableRowsProportions.Add( proportion );
1333 }
1334
1335 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1336 {
1337 m_growableRows.Remove( idx );
1338 }
1339
1340 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1341 {
1342 m_growableCols.Add( idx );
1343 m_growableColsProportions.Add( proportion );
1344 }
1345
1346 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1347 {
1348 m_growableCols.Remove( idx );
1349 }
1350
1351 //---------------------------------------------------------------------------
1352 // wxBoxSizer
1353 //---------------------------------------------------------------------------
1354
1355 wxBoxSizer::wxBoxSizer( int orient )
1356 : m_orient( orient )
1357 {
1358 }
1359
1360 void wxBoxSizer::RecalcSizes()
1361 {
1362 if (m_children.GetCount() == 0)
1363 return;
1364
1365 int delta = 0;
1366 if (m_stretchable)
1367 {
1368 if (m_orient == wxHORIZONTAL)
1369 delta = m_size.x - m_fixedWidth;
1370 else
1371 delta = m_size.y - m_fixedHeight;
1372 }
1373
1374 wxPoint pt( m_position );
1375
1376 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1377 while (node)
1378 {
1379 wxSizerItem *item = node->GetData();
1380
1381 if (item->IsShown())
1382 {
1383 wxSize size( item->CalcMin() );
1384
1385 if (m_orient == wxVERTICAL)
1386 {
1387 wxCoord height = size.y;
1388 if (item->GetProportion())
1389 {
1390 // Because of at least one visible item has non-zero
1391 // proportion then m_stretchable is not zero
1392 height = (delta * item->GetProportion()) / m_stretchable;
1393 }
1394
1395 wxPoint child_pos( pt );
1396 wxSize child_size( wxSize( size.x, height) );
1397
1398 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1399 child_size.x = m_size.x;
1400 else if (item->GetFlag() & wxALIGN_RIGHT)
1401 child_pos.x += m_size.x - size.x;
1402 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1403 // XXX wxCENTER is added for backward compatibility;
1404 // wxALIGN_CENTER should be used in new code
1405 child_pos.x += (m_size.x - size.x) / 2;
1406
1407 item->SetDimension( child_pos, child_size );
1408
1409 pt.y += height;
1410 }
1411 else
1412 {
1413 wxCoord width = size.x;
1414 if (item->GetProportion())
1415 {
1416 // Because of at least one visible item has non-zero
1417 // proportion then m_stretchable is not zero
1418 width = (delta * item->GetProportion()) / m_stretchable;
1419 }
1420
1421 wxPoint child_pos( pt );
1422 wxSize child_size( wxSize(width, size.y) );
1423
1424 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1425 child_size.y = m_size.y;
1426 else if (item->GetFlag() & wxALIGN_BOTTOM)
1427 child_pos.y += m_size.y - size.y;
1428 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1429 // XXX wxCENTER is added for backward compatibility;
1430 // wxALIGN_CENTER should be used in new code
1431 child_pos.y += (m_size.y - size.y) / 2;
1432
1433 item->SetDimension( child_pos, child_size );
1434
1435 pt.x += width;
1436 }
1437 }
1438
1439 node = node->GetNext();
1440 }
1441 }
1442
1443 wxSize wxBoxSizer::CalcMin()
1444 {
1445 if (m_children.GetCount() == 0)
1446 return wxSize(10,10);
1447
1448 m_stretchable = 0;
1449 m_minWidth = 0;
1450 m_minHeight = 0;
1451 m_fixedWidth = 0;
1452 m_fixedHeight = 0;
1453
1454 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1455 while (node)
1456 {
1457 wxSizerItem *item = node->GetData();
1458
1459 if (item->IsShown() && item->GetProportion() != 0)
1460 m_stretchable += item->GetProportion();
1461
1462 node = node->GetNext();
1463 }
1464
1465 // Total minimum size (width or height) of sizer
1466 int maxMinSize = 0;
1467
1468 node = m_children.GetFirst();
1469 while (node)
1470 {
1471 wxSizerItem *item = node->GetData();
1472
1473 if (item->IsShown() && item->GetProportion() != 0)
1474 {
1475 int stretch = item->GetProportion();
1476 wxSize size( item->CalcMin() );
1477 int minSize;
1478
1479 // Integer division rounded up is (a + b - 1) / b
1480 // Round up needed in order to guarantee that all
1481 // all items will have size not less then their min size
1482 if (m_orient == wxHORIZONTAL)
1483 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1484 else
1485 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1486
1487 if (minSize > maxMinSize)
1488 maxMinSize = minSize;
1489 }
1490 node = node->GetNext();
1491 }
1492
1493 // Calculate overall minimum size
1494 node = m_children.GetFirst();
1495 while (node)
1496 {
1497 wxSizerItem *item = node->GetData();
1498
1499 if (item->IsShown())
1500 {
1501 wxSize size( item->CalcMin() );
1502 if (item->GetProportion() != 0)
1503 {
1504 if (m_orient == wxHORIZONTAL)
1505 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1506 else
1507 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1508 }
1509 else
1510 {
1511 if (m_orient == wxVERTICAL)
1512 {
1513 m_fixedHeight += size.y;
1514 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1515 }
1516 else
1517 {
1518 m_fixedWidth += size.x;
1519 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1520 }
1521 }
1522
1523 if (m_orient == wxHORIZONTAL)
1524 {
1525 m_minWidth += size.x;
1526 m_minHeight = wxMax( m_minHeight, size.y );
1527 }
1528 else
1529 {
1530 m_minHeight += size.y;
1531 m_minWidth = wxMax( m_minWidth, size.x );
1532 }
1533 }
1534 node = node->GetNext();
1535 }
1536
1537 return wxSize( m_minWidth, m_minHeight );
1538 }
1539
1540 //---------------------------------------------------------------------------
1541 // wxStaticBoxSizer
1542 //---------------------------------------------------------------------------
1543
1544 #if wxUSE_STATBOX
1545
1546 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1547 : wxBoxSizer( orient )
1548 , m_staticBox( box )
1549 {
1550 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1551 }
1552
1553 static void GetStaticBoxBorders( wxStaticBox *box,
1554 int *borderTop,
1555 int *borderOther)
1556 {
1557 // this has to be done platform by platform as there is no way to
1558 // guess the thickness of a wxStaticBox border
1559 #ifdef __WXCOCOA__
1560 box->GetBordersForSizer(borderTop,borderOther);
1561 #elif defined(__WXMAC__)
1562
1563 static int extraTop = -1; // Uninitted
1564 static int other = 5;
1565
1566 if ( extraTop == -1 )
1567 {
1568 // The minimal border used for the top. Later on the staticbox'
1569 // font height is added to this.
1570 extraTop = 0;
1571
1572 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1573 {
1574 // As indicated by the HIG, Panther needs an extra border of 11
1575 // pixels (otherwise overlapping occurs at the top). The "other"
1576 // border has to be 11.
1577 extraTop = 11;
1578 other = 11;
1579 }
1580
1581 }
1582
1583 *borderTop = extraTop + box->GetCharHeight();
1584 *borderOther = other;
1585
1586 #else
1587 #ifdef __WXGTK__
1588 if ( box->GetLabel().IsEmpty() )
1589 *borderTop = 5;
1590 else
1591 #endif // __WXGTK__
1592 *borderTop = box->GetCharHeight();
1593
1594 *borderOther = 5;
1595 #endif // __WXCOCOA__
1596 }
1597
1598 void wxStaticBoxSizer::RecalcSizes()
1599 {
1600 int top_border, other_border;
1601 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1602
1603 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1604
1605 wxPoint old_pos( m_position );
1606 m_position.x += other_border;
1607 m_position.y += top_border;
1608 wxSize old_size( m_size );
1609 m_size.x -= 2*other_border;
1610 m_size.y -= top_border + other_border;
1611
1612 wxBoxSizer::RecalcSizes();
1613
1614 m_position = old_pos;
1615 m_size = old_size;
1616 }
1617
1618 wxSize wxStaticBoxSizer::CalcMin()
1619 {
1620 int top_border, other_border;
1621 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1622
1623 wxSize ret( wxBoxSizer::CalcMin() );
1624 ret.x += 2*other_border;
1625 ret.y += other_border + top_border;
1626
1627 return ret;
1628 }
1629
1630 #endif // wxUSE_STATBOX
1631
1632 // ----------------------------------------------------------------------------
1633 // wxNotebookSizer
1634 // ----------------------------------------------------------------------------
1635
1636 #if wxUSE_BOOKCTRL
1637
1638 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1639 : m_bookctrl(bookctrl)
1640 {
1641 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1642 }
1643
1644 void wxBookCtrlSizer::RecalcSizes()
1645 {
1646 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1647 }
1648
1649 wxSize wxBookCtrlSizer::CalcMin()
1650 {
1651 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1652
1653 sizeBorder.x += 5;
1654 sizeBorder.y += 5;
1655
1656 if ( m_bookctrl->GetPageCount() == 0 )
1657 {
1658 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1659 }
1660
1661 int maxX = 0;
1662 int maxY = 0;
1663
1664 wxWindowList::compatibility_iterator
1665 node = m_bookctrl->GetChildren().GetFirst();
1666 while (node)
1667 {
1668 wxWindow *item = node->GetData();
1669 wxSizer *itemsizer = item->GetSizer();
1670
1671 if (itemsizer)
1672 {
1673 wxSize subsize( itemsizer->CalcMin() );
1674
1675 if (subsize.x > maxX)
1676 maxX = subsize.x;
1677 if (subsize.y > maxY)
1678 maxY = subsize.y;
1679 }
1680
1681 node = node->GetNext();
1682 }
1683
1684 return wxSize( maxX, maxY ) + sizeBorder;
1685 }
1686
1687
1688 #if wxUSE_NOTEBOOK
1689
1690 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1691 : wxBookCtrlSizer(nb)
1692 {
1693 }
1694
1695 #endif // wxUSE_NOTEBOOOK
1696 #endif // wxUSE_BOOKCTRL
1697