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