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