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