]> git.saurik.com Git - wxWidgets.git/blob - src/common/sizer.cpp
Compilation fix for Innotek gcc.
[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 // Return a window size that will fit within the screens dimensions
649 wxSize wxSizer::FitSize( wxWindow *window )
650 {
651 wxSize size = GetMinWindowSize( window );
652 wxSize sizeMax = GetMaxWindowSize( window );
653
654 // Limit the size if sizeMax != wxDefaultSize
655
656 if ( size.x > sizeMax.x && sizeMax.x != -1 )
657 size.x = sizeMax.x;
658 if ( size.y > sizeMax.y && sizeMax.y != -1 )
659 size.y = sizeMax.y;
660
661 return size;
662 }
663
664 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
665 {
666 wxSize maxSize( window->GetMaxSize() );
667
668 if( maxSize != wxDefaultSize )
669 {
670 wxSize size( window->GetSize() );
671 wxSize client_size( window->GetClientSize() );
672
673 return wxSize( maxSize.x + client_size.x - size.x,
674 maxSize.y + client_size.y - size.y );
675 }
676 else
677 return wxDefaultSize;
678 }
679
680 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
681 {
682 return GetMinSize(); // Already returns client size.
683 }
684
685 wxSize wxSizer::VirtualFitSize( wxWindow *window )
686 {
687 wxSize size = GetMinClientSize( window );
688 wxSize sizeMax = GetMaxClientSize( window );
689
690 // Limit the size if sizeMax != wxDefaultSize
691
692 if ( size.x > sizeMax.x && sizeMax.x != -1 )
693 size.x = sizeMax.x;
694 if ( size.y > sizeMax.y && sizeMax.y != -1 )
695 size.y = sizeMax.y;
696
697 return size;
698 }
699
700 void wxSizer::SetDimension( int x, int y, int width, int height )
701 {
702 m_position.x = x;
703 m_position.y = y;
704 m_size.x = width;
705 m_size.y = height;
706 Layout();
707 }
708
709 wxSize wxSizer::GetMinSize()
710 {
711 wxSize ret( CalcMin() );
712 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
713 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
714 return ret;
715 }
716
717 void wxSizer::DoSetMinSize( int width, int height )
718 {
719 m_minSize.x = width;
720 m_minSize.y = height;
721 }
722
723 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
724 {
725 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
726
727 // Is it our immediate child?
728
729 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
730 while (node)
731 {
732 wxSizerItem *item = node->GetData();
733
734 if (item->GetWindow() == window)
735 {
736 item->SetInitSize( width, height );
737 return true;
738 }
739 node = node->GetNext();
740 }
741
742 // No? Search any subsizers we own then
743
744 node = m_children.GetFirst();
745 while (node)
746 {
747 wxSizerItem *item = node->GetData();
748
749 if ( item->GetSizer() &&
750 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
751 {
752 // A child sizer found the requested windw, exit.
753 return true;
754 }
755 node = node->GetNext();
756 }
757
758 return false;
759 }
760
761 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
762 {
763 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
764
765 // Is it our immediate child?
766
767 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
768 while (node)
769 {
770 wxSizerItem *item = node->GetData();
771
772 if (item->GetSizer() == sizer)
773 {
774 item->GetSizer()->DoSetMinSize( width, height );
775 return true;
776 }
777 node = node->GetNext();
778 }
779
780 // No? Search any subsizers we own then
781
782 node = m_children.GetFirst();
783 while (node)
784 {
785 wxSizerItem *item = node->GetData();
786
787 if ( item->GetSizer() &&
788 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
789 {
790 // A child found the requested sizer, exit.
791 return true;
792 }
793 node = node->GetNext();
794 }
795
796 return false;
797 }
798
799 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
800 {
801 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
802
803 wxCHECK_MSG( node, false, _T("Failed to find child node") );
804
805 wxSizerItem *item = node->GetData();
806
807 if (item->GetSizer())
808 {
809 // Sizers contains the minimal size in them, if not calculated ...
810 item->GetSizer()->DoSetMinSize( width, height );
811 }
812 else
813 {
814 // ... but the minimal size of spacers and windows in stored in them
815 item->SetInitSize( width, height );
816 }
817
818 return true;
819 }
820
821 void wxSizer::Show( wxWindow *window, bool show )
822 {
823 wxASSERT_MSG( window, _T("Show for NULL window") );
824
825 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
826 while (node)
827 {
828 wxSizerItem *item = node->GetData();
829
830 if (item->GetWindow() == window)
831 {
832 item->Show( show );
833 break;
834 }
835 node = node->GetNext();
836 }
837 }
838
839 void wxSizer::Show( wxSizer *sizer, bool show )
840 {
841 wxASSERT_MSG( sizer, _T("Show for NULL sizer") );
842
843 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
844 while (node)
845 {
846 wxSizerItem *item = node->GetData();
847
848 if (item->GetSizer() == sizer)
849 {
850 item->Show( show );
851 break;
852 }
853 node = node->GetNext();
854 }
855 }
856
857 void wxSizer::Show( size_t index, bool show )
858 {
859 wxCHECK_RET( index < m_children.GetCount(),
860 _T("Show index is out of range") );
861
862 m_children.Item( index )->GetData()->Show( show );
863 }
864
865 void wxSizer::ShowItems( bool show )
866 {
867 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
868 while (node)
869 {
870 node->GetData()->Show( show );
871 node = node->GetNext();
872 }
873 }
874
875 bool wxSizer::IsShown( wxWindow *window ) const
876 {
877 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
878 while (node)
879 {
880 wxSizerItem *item = node->GetData();
881
882 if (item->GetWindow() == window)
883 {
884 return item->IsShown();
885 }
886 node = node->GetNext();
887 }
888
889 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
890
891 return false;
892 }
893
894 bool wxSizer::IsShown( wxSizer *sizer ) const
895 {
896 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
897 while (node)
898 {
899 wxSizerItem *item = node->GetData();
900
901 if (item->GetSizer() == sizer)
902 {
903 return item->IsShown();
904 }
905 node = node->GetNext();
906 }
907
908 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
909
910 return false;
911 }
912
913 bool wxSizer::IsShown( size_t index ) const
914 {
915 wxCHECK_MSG( index < m_children.GetCount(),
916 false,
917 _T("IsShown index is out of range") );
918
919 return m_children.Item( index )->GetData()->IsShown();
920 }
921
922
923 //---------------------------------------------------------------------------
924 // wxGridSizer
925 //---------------------------------------------------------------------------
926
927 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
928 : m_rows( rows )
929 , m_cols( cols )
930 , m_vgap( vgap )
931 , m_hgap( hgap )
932 {
933 if (m_rows == 0 && m_cols == 0)
934 m_rows = 1;
935 }
936
937 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
938 : m_rows( 0 )
939 , m_cols( cols )
940 , m_vgap( vgap )
941 , m_hgap( hgap )
942 {
943 if (m_rows == 0 && m_cols == 0)
944 m_rows = 1;
945 }
946
947 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
948 {
949 int nitems = m_children.GetCount();
950 if ( nitems)
951 {
952 if ( m_cols )
953 {
954 ncols = m_cols;
955 nrows = (nitems + m_cols - 1) / m_cols;
956 }
957 else if ( m_rows )
958 {
959 ncols = (nitems + m_rows - 1) / m_rows;
960 nrows = m_rows;
961 }
962 else // 0 columns, 0 rows?
963 {
964 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
965
966 nrows = ncols = 0;
967 }
968 }
969
970 return nitems;
971 }
972
973 void wxGridSizer::RecalcSizes()
974 {
975 int nitems, nrows, ncols;
976 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
977 return;
978
979 wxSize sz( GetSize() );
980 wxPoint pt( GetPosition() );
981
982 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
983 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
984
985 int x = pt.x;
986 for (int c = 0; c < ncols; c++)
987 {
988 int y = pt.y;
989 for (int r = 0; r < nrows; r++)
990 {
991 int i = r * ncols + c;
992 if (i < nitems)
993 {
994 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
995
996 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
997
998 SetItemBounds( node->GetData(), x, y, w, h);
999 }
1000 y = y + h + m_vgap;
1001 }
1002 x = x + w + m_hgap;
1003 }
1004 }
1005
1006 wxSize wxGridSizer::CalcMin()
1007 {
1008 int nrows, ncols;
1009 if ( CalcRowsCols(nrows, ncols) == 0 )
1010 return wxSize(10, 10);
1011
1012 // Find the max width and height for any component
1013 int w = 0;
1014 int h = 0;
1015
1016 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1017 while (node)
1018 {
1019 wxSizerItem *item = node->GetData();
1020 wxSize sz( item->CalcMin() );
1021
1022 w = wxMax( w, sz.x );
1023 h = wxMax( h, sz.y );
1024
1025 node = node->GetNext();
1026 }
1027
1028 return wxSize( ncols * w + (ncols-1) * m_hgap,
1029 nrows * h + (nrows-1) * m_vgap );
1030 }
1031
1032 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1033 {
1034 wxPoint pt( x,y );
1035 wxSize sz( item->CalcMin() );
1036 int flag = item->GetFlag();
1037
1038 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1039 {
1040 sz = wxSize(w, h);
1041 }
1042 else
1043 {
1044 if (flag & wxALIGN_CENTER_HORIZONTAL)
1045 {
1046 pt.x = x + (w - sz.x) / 2;
1047 }
1048 else if (flag & wxALIGN_RIGHT)
1049 {
1050 pt.x = x + (w - sz.x);
1051 }
1052
1053 if (flag & wxALIGN_CENTER_VERTICAL)
1054 {
1055 pt.y = y + (h - sz.y) / 2;
1056 }
1057 else if (flag & wxALIGN_BOTTOM)
1058 {
1059 pt.y = y + (h - sz.y);
1060 }
1061 }
1062
1063 item->SetDimension(pt, sz);
1064 }
1065
1066 //---------------------------------------------------------------------------
1067 // wxFlexGridSizer
1068 //---------------------------------------------------------------------------
1069
1070 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1071 : wxGridSizer( rows, cols, vgap, hgap ),
1072 m_flexDirection(wxBOTH),
1073 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1074 {
1075 }
1076
1077 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1078 : wxGridSizer( cols, vgap, hgap ),
1079 m_flexDirection(wxBOTH),
1080 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1081 {
1082 }
1083
1084 wxFlexGridSizer::~wxFlexGridSizer()
1085 {
1086 }
1087
1088 void wxFlexGridSizer::RecalcSizes()
1089 {
1090 int nitems, nrows, ncols;
1091 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1092 return;
1093
1094 wxPoint pt( GetPosition() );
1095 wxSize sz( GetSize() );
1096 wxSize minsz( CalcMin() );
1097
1098 AdjustForGrowables(sz, minsz, nrows, ncols);
1099
1100 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1101
1102 int x = pt.x;
1103 for (int c = 0; c < ncols; c++)
1104 {
1105 int y = pt.y;
1106 for (int r = 0; r < nrows; r++)
1107 {
1108 int i = r * ncols + c;
1109 if (i < nitems)
1110 {
1111 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1112
1113 wxASSERT_MSG( node, _T("Failed to find node") );
1114
1115 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1116 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1117
1118 SetItemBounds( node->GetData(), x, y, w, h);
1119 }
1120 y = y + m_rowHeights[r] + m_vgap;
1121 }
1122 x = x + m_colWidths[c] + m_hgap;
1123 }
1124 }
1125
1126 wxSize wxFlexGridSizer::CalcMin()
1127 {
1128 int nrows,
1129 ncols;
1130 size_t i, s;
1131
1132 // Number of rows/columns can change as items are added or removed.
1133 if ( !CalcRowsCols(nrows, ncols) )
1134 return wxSize(10, 10);
1135
1136 m_rowHeights.SetCount(nrows);
1137 m_colWidths.SetCount(ncols);
1138
1139 // We have to recalcuate the sizes in case an item has wxADJUST_MINSIZE, has changed
1140 // minimum size since the previous layout, or has been hidden using wxSizer::Show().
1141 // If all the items in a row/column are hidden, the final dimension of the row/column
1142 // will be -1, indicating that the column itself is hidden.
1143 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1144 m_rowHeights[ i ] = -1;
1145 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1146 m_colWidths[ i ] = -1;
1147
1148 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1149
1150 i = 0;
1151 while (node)
1152 {
1153 wxSizerItem *item = node->GetData();
1154 if ( item->IsShown() )
1155 {
1156 wxSize sz( item->CalcMin() );
1157 int row = i / ncols;
1158 int col = i % ncols;
1159
1160 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1161 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1162 }
1163
1164 node = node->GetNext();
1165 i++;
1166 }
1167
1168 AdjustForFlexDirection();
1169
1170 // Sum total minimum size, including gaps between rows/columns.
1171 // -1 is used as a magic number meaning empty column.
1172 int width = 0;
1173 for (int col = 0; col < ncols; col++)
1174 if ( m_colWidths[ col ] != -1 )
1175 width += m_colWidths[ col ] + ( col == ncols-1 ? 0 : m_hgap );
1176
1177 int height = 0;
1178 for (int row = 0; row < nrows; row++)
1179 if ( m_rowHeights[ row ] != -1 )
1180 height += m_rowHeights[ row ] + ( row == nrows-1 ? 0 : m_vgap );
1181
1182 return wxSize( width, height );
1183 }
1184
1185 void wxFlexGridSizer::AdjustForFlexDirection()
1186 {
1187 // the logic in CalcMin works when we resize flexibly in both directions
1188 // but maybe this is not the case
1189 if ( m_flexDirection != wxBOTH )
1190 {
1191 // select the array corresponding to the direction in which we do *not*
1192 // resize flexibly
1193 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1194 : m_rowHeights;
1195
1196 const int count = array.GetCount();
1197
1198 // find the largest value in this array
1199 int n, largest = 0;
1200 for ( n = 0; n < count; ++n )
1201 {
1202 if ( array[n] > largest )
1203 largest = array[n];
1204 }
1205
1206 // and now fill it with the largest value
1207 for ( n = 0; n < count; ++n )
1208 {
1209 array[n] = largest;
1210 }
1211 }
1212 }
1213
1214
1215 void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1216 int nrows, int ncols)
1217 {
1218 // what to do with the rows? by default, resize them proportionally
1219 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1220 {
1221 int sum_proportions = 0;
1222 int growable_space = 0;
1223 int num = 0;
1224 size_t idx;
1225 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1226 {
1227 // Since the number of rows/columns can change as items are
1228 // inserted/deleted, we need to verify at runtime that the
1229 // requested growable rows/columns are still valid.
1230 if (m_growableRows[idx] >= nrows)
1231 continue;
1232
1233 // If all items in a row/column are hidden, that row/column will
1234 // have a dimension of -1. This causes the row/column to be
1235 // hidden completely.
1236 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1237 continue;
1238 sum_proportions += m_growableRowsProportions[idx];
1239 growable_space += m_rowHeights[ m_growableRows[idx] ];
1240 num++;
1241 }
1242
1243 if (num > 0)
1244 {
1245 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1246 {
1247 if (m_growableRows[idx] >= nrows )
1248 continue;
1249 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1250 m_rowHeights[ m_growableRows[idx] ] = 0;
1251 else
1252 {
1253 int delta = (sz.y - minsz.y);
1254 if (sum_proportions == 0)
1255 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1256 else
1257 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1258 m_rowHeights[ m_growableRows[idx] ] = delta;
1259 }
1260 }
1261 }
1262 }
1263 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1264 {
1265 // rounding problem?
1266 for ( int row = 0; row < nrows; ++row )
1267 m_rowHeights[ row ] = sz.y / nrows;
1268 }
1269
1270 // the same logic as above but for the columns
1271 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1272 {
1273 int sum_proportions = 0;
1274 int growable_space = 0;
1275 int num = 0;
1276 size_t idx;
1277 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1278 {
1279 // Since the number of rows/columns can change as items are
1280 // inserted/deleted, we need to verify at runtime that the
1281 // requested growable rows/columns are still valid.
1282 if (m_growableCols[idx] >= ncols)
1283 continue;
1284
1285 // If all items in a row/column are hidden, that row/column will
1286 // have a dimension of -1. This causes the column to be hidden
1287 // completely.
1288 if (m_colWidths[ m_growableCols[idx] ] == -1)
1289 continue;
1290 sum_proportions += m_growableColsProportions[idx];
1291 growable_space += m_colWidths[ m_growableCols[idx] ];
1292 num++;
1293 }
1294
1295 if (num > 0)
1296 {
1297 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1298 {
1299 if (m_growableCols[idx] >= ncols )
1300 continue;
1301 if (m_colWidths[ m_growableCols[idx] ] == -1)
1302 m_colWidths[ m_growableCols[idx] ] = 0;
1303 else
1304 {
1305 int delta = (sz.x - minsz.x);
1306 if (sum_proportions == 0)
1307 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1308 else
1309 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1310 m_colWidths[ m_growableCols[idx] ] = delta;
1311 }
1312 }
1313 }
1314 }
1315 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1316 {
1317 for ( int col=0; col < ncols; ++col )
1318 m_colWidths[ col ] = sz.x / ncols;
1319 }
1320 }
1321
1322
1323 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1324 {
1325 m_growableRows.Add( idx );
1326 m_growableRowsProportions.Add( proportion );
1327 }
1328
1329 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1330 {
1331 m_growableRows.Remove( idx );
1332 }
1333
1334 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1335 {
1336 m_growableCols.Add( idx );
1337 m_growableColsProportions.Add( proportion );
1338 }
1339
1340 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1341 {
1342 m_growableCols.Remove( idx );
1343 }
1344
1345 //---------------------------------------------------------------------------
1346 // wxBoxSizer
1347 //---------------------------------------------------------------------------
1348
1349 wxBoxSizer::wxBoxSizer( int orient )
1350 : m_orient( orient )
1351 {
1352 }
1353
1354 void wxBoxSizer::RecalcSizes()
1355 {
1356 if (m_children.GetCount() == 0)
1357 return;
1358
1359 int delta = 0;
1360 if (m_stretchable)
1361 {
1362 if (m_orient == wxHORIZONTAL)
1363 delta = m_size.x - m_fixedWidth;
1364 else
1365 delta = m_size.y - m_fixedHeight;
1366 }
1367
1368 wxPoint pt( m_position );
1369
1370 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1371 while (node)
1372 {
1373 wxSizerItem *item = node->GetData();
1374
1375 if (item->IsShown())
1376 {
1377 wxSize size( item->CalcMin() );
1378
1379 if (m_orient == wxVERTICAL)
1380 {
1381 wxCoord height = size.y;
1382 if (item->GetProportion())
1383 {
1384 // Because of at least one visible item has non-zero
1385 // proportion then m_stretchable is not zero
1386 height = (delta * item->GetProportion()) / m_stretchable;
1387 }
1388
1389 wxPoint child_pos( pt );
1390 wxSize child_size( wxSize( size.x, height) );
1391
1392 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1393 child_size.x = m_size.x;
1394 else if (item->GetFlag() & wxALIGN_RIGHT)
1395 child_pos.x += m_size.x - size.x;
1396 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1397 // XXX wxCENTER is added for backward compatibility;
1398 // wxALIGN_CENTER should be used in new code
1399 child_pos.x += (m_size.x - size.x) / 2;
1400
1401 item->SetDimension( child_pos, child_size );
1402
1403 pt.y += height;
1404 }
1405 else
1406 {
1407 wxCoord width = size.x;
1408 if (item->GetProportion())
1409 {
1410 // Because of at least one visible item has non-zero
1411 // proportion then m_stretchable is not zero
1412 width = (delta * item->GetProportion()) / m_stretchable;
1413 }
1414
1415 wxPoint child_pos( pt );
1416 wxSize child_size( wxSize(width, size.y) );
1417
1418 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1419 child_size.y = m_size.y;
1420 else if (item->GetFlag() & wxALIGN_BOTTOM)
1421 child_pos.y += m_size.y - size.y;
1422 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1423 // XXX wxCENTER is added for backward compatibility;
1424 // wxALIGN_CENTER should be used in new code
1425 child_pos.y += (m_size.y - size.y) / 2;
1426
1427 item->SetDimension( child_pos, child_size );
1428
1429 pt.x += width;
1430 }
1431 }
1432
1433 node = node->GetNext();
1434 }
1435 }
1436
1437 wxSize wxBoxSizer::CalcMin()
1438 {
1439 if (m_children.GetCount() == 0)
1440 return wxSize(10,10);
1441
1442 m_stretchable = 0;
1443 m_minWidth = 0;
1444 m_minHeight = 0;
1445 m_fixedWidth = 0;
1446 m_fixedHeight = 0;
1447
1448 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1449 while (node)
1450 {
1451 wxSizerItem *item = node->GetData();
1452
1453 if (item->IsShown() && item->GetProportion() != 0)
1454 m_stretchable += item->GetProportion();
1455
1456 node = node->GetNext();
1457 }
1458
1459 // Total minimum size (width or height) of sizer
1460 int maxMinSize = 0;
1461
1462 node = m_children.GetFirst();
1463 while (node)
1464 {
1465 wxSizerItem *item = node->GetData();
1466
1467 if (item->IsShown() && item->GetProportion() != 0)
1468 {
1469 int stretch = item->GetProportion();
1470 wxSize size( item->CalcMin() );
1471 int minSize;
1472
1473 // Integer division rounded up is (a + b - 1) / b
1474 // Round up needed in order to guarantee that all
1475 // all items will have size not less then their min size
1476 if (m_orient == wxHORIZONTAL)
1477 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1478 else
1479 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1480
1481 if (minSize > maxMinSize)
1482 maxMinSize = minSize;
1483 }
1484 node = node->GetNext();
1485 }
1486
1487 // Calculate overall minimum size
1488 node = m_children.GetFirst();
1489 while (node)
1490 {
1491 wxSizerItem *item = node->GetData();
1492
1493 if (item->IsShown())
1494 {
1495 wxSize size( item->CalcMin() );
1496 if (item->GetProportion() != 0)
1497 {
1498 if (m_orient == wxHORIZONTAL)
1499 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1500 else
1501 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1502 }
1503 else
1504 {
1505 if (m_orient == wxVERTICAL)
1506 {
1507 m_fixedHeight += size.y;
1508 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1509 }
1510 else
1511 {
1512 m_fixedWidth += size.x;
1513 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1514 }
1515 }
1516
1517 if (m_orient == wxHORIZONTAL)
1518 {
1519 m_minWidth += size.x;
1520 m_minHeight = wxMax( m_minHeight, size.y );
1521 }
1522 else
1523 {
1524 m_minHeight += size.y;
1525 m_minWidth = wxMax( m_minWidth, size.x );
1526 }
1527 }
1528 node = node->GetNext();
1529 }
1530
1531 return wxSize( m_minWidth, m_minHeight );
1532 }
1533
1534 //---------------------------------------------------------------------------
1535 // wxStaticBoxSizer
1536 //---------------------------------------------------------------------------
1537
1538 #if wxUSE_STATBOX
1539
1540 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1541 : wxBoxSizer( orient )
1542 , m_staticBox( box )
1543 {
1544 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1545 }
1546
1547 static void GetStaticBoxBorders( wxStaticBox *box,
1548 int *borderTop,
1549 int *borderOther)
1550 {
1551 // this has to be done platform by platform as there is no way to
1552 // guess the thickness of a wxStaticBox border
1553 #ifdef __WXCOCOA__
1554 box->GetBordersForSizer(borderTop,borderOther);
1555 #elif defined(__WXMAC__)
1556
1557 static int extraTop = -1; // Uninitted
1558 static int other = 5;
1559
1560 if ( extraTop == -1 )
1561 {
1562 // The minimal border used for the top. Later on the staticbox'
1563 // font height is added to this.
1564 extraTop = 0;
1565
1566 if ( UMAGetSystemVersion() >= 0x1030 /*Panther*/ )
1567 {
1568 // As indicated by the HIG, Panther needs an extra border of 11
1569 // pixels (otherwise overlapping occurs at the top). The "other"
1570 // border has to be 11.
1571 extraTop = 11;
1572 other = 11;
1573 }
1574
1575 }
1576
1577 *borderTop = extraTop + box->GetCharHeight();
1578 *borderOther = other;
1579
1580 #else
1581 #ifdef __WXGTK__
1582 if ( box->GetLabel().IsEmpty() )
1583 *borderTop = 5;
1584 else
1585 #endif // __WXGTK__
1586 *borderTop = box->GetCharHeight();
1587
1588 *borderOther = 5;
1589 #endif // __WXCOCOA__
1590 }
1591
1592 void wxStaticBoxSizer::RecalcSizes()
1593 {
1594 int top_border, other_border;
1595 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1596
1597 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1598
1599 wxPoint old_pos( m_position );
1600 m_position.x += other_border;
1601 m_position.y += top_border;
1602 wxSize old_size( m_size );
1603 m_size.x -= 2*other_border;
1604 m_size.y -= top_border + other_border;
1605
1606 wxBoxSizer::RecalcSizes();
1607
1608 m_position = old_pos;
1609 m_size = old_size;
1610 }
1611
1612 wxSize wxStaticBoxSizer::CalcMin()
1613 {
1614 int top_border, other_border;
1615 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1616
1617 wxSize ret( wxBoxSizer::CalcMin() );
1618 ret.x += 2*other_border;
1619 ret.y += other_border + top_border;
1620
1621 return ret;
1622 }
1623
1624 #endif // wxUSE_STATBOX
1625
1626 // ----------------------------------------------------------------------------
1627 // wxNotebookSizer
1628 // ----------------------------------------------------------------------------
1629
1630 #if wxUSE_BOOKCTRL
1631
1632 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrl *bookctrl)
1633 : m_bookctrl(bookctrl)
1634 {
1635 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
1636 }
1637
1638 void wxBookCtrlSizer::RecalcSizes()
1639 {
1640 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1641 }
1642
1643 wxSize wxBookCtrlSizer::CalcMin()
1644 {
1645 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0, 0));
1646
1647 sizeBorder.x += 5;
1648 sizeBorder.y += 5;
1649
1650 if ( m_bookctrl->GetPageCount() == 0 )
1651 {
1652 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
1653 }
1654
1655 int maxX = 0;
1656 int maxY = 0;
1657
1658 wxWindowList::compatibility_iterator
1659 node = m_bookctrl->GetChildren().GetFirst();
1660 while (node)
1661 {
1662 wxWindow *item = node->GetData();
1663 wxSizer *itemsizer = item->GetSizer();
1664
1665 if (itemsizer)
1666 {
1667 wxSize subsize( itemsizer->CalcMin() );
1668
1669 if (subsize.x > maxX)
1670 maxX = subsize.x;
1671 if (subsize.y > maxY)
1672 maxY = subsize.y;
1673 }
1674
1675 node = node->GetNext();
1676 }
1677
1678 return wxSize( maxX, maxY ) + sizeBorder;
1679 }
1680
1681
1682 #if wxUSE_NOTEBOOK
1683
1684 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
1685 : wxBookCtrlSizer(nb)
1686 {
1687 }
1688
1689 #endif // wxUSE_NOTEBOOOK
1690 #endif // wxUSE_BOOKCTRL
1691