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