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