1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: provide new wxSizer class for layout
4 // Author: Robert Roebling and Robin Dunn
5 // Modified by: Ron Lee
8 // Copyright: (c) Robin Dunn, Dirk Holtwick and Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "sizer.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/statbox.h"
26 #include "wx/notebook.h"
28 //---------------------------------------------------------------------------
30 IMPLEMENT_ABSTRACT_CLASS(wxSizerItem
, wxObject
)
31 IMPLEMENT_ABSTRACT_CLASS(wxSizer
, wxObject
)
32 IMPLEMENT_ABSTRACT_CLASS(wxGridSizer
, wxSizer
)
33 IMPLEMENT_ABSTRACT_CLASS(wxFlexGridSizer
, wxGridSizer
)
34 IMPLEMENT_ABSTRACT_CLASS(wxBoxSizer
, wxSizer
)
36 IMPLEMENT_ABSTRACT_CLASS(wxStaticBoxSizer
, wxBoxSizer
)
39 IMPLEMENT_ABSTRACT_CLASS(wxNotebookSizer
, wxSizer
)
42 //---------------------------------------------------------------------------
44 //---------------------------------------------------------------------------
46 wxSizerItem::wxSizerItem( int width
, int height
, int option
, int flag
, int border
, wxObject
* userData
)
49 , m_size( wxSize( width
, height
) ) // size is set directly
50 , m_minSize( m_size
) // minimal size is the initial size
54 , m_show( TRUE
) // Cannot be changed
55 , m_userData( userData
)
60 wxSizerItem::wxSizerItem( wxWindow
*window
, int option
, int flag
, int border
, wxObject
* userData
)
63 , m_minSize( window
->GetSize() ) // minimal size is the initial size
68 , m_userData( userData
)
70 // aspect ratio calculated from initial size
71 SetRatio( m_minSize
);
73 // m_size is calculated later
76 wxSizerItem::wxSizerItem( wxSizer
*sizer
, int option
, int flag
, int border
, wxObject
* userData
)
84 , m_userData( userData
)
86 // m_minSize is calculated later
87 // m_size is calculated later
90 wxSizerItem::~wxSizerItem()
99 wxSize
wxSizerItem::GetSize()
103 ret
= m_sizer
->GetSize();
106 ret
= m_window
->GetSize();
113 if (m_flag
& wxNORTH
)
115 if (m_flag
& wxSOUTH
)
121 wxSize
wxSizerItem::CalcMin()
126 ret
= m_sizer
->GetMinSize();
128 // if we have to preserve aspect ratio _AND_ this is
129 // the first-time calculation, consider ret to be initial size
130 if ((m_flag
& wxSHAPED
) && !m_ratio
)
135 if ( IsWindow() && (m_flag
& wxADJUST_MINSIZE
) )
137 // By user request, keep the minimal size for this item
138 // in sync with the largest of BestSize and any user supplied
139 // minimum size hint. Useful in cases where the item is
140 // changeable -- static text labels, etc.
141 m_minSize
= m_window
->GetAdjustedBestSize();
151 if (m_flag
& wxNORTH
)
153 if (m_flag
& wxSOUTH
)
159 void wxSizerItem::SetDimension( wxPoint pos
, wxSize size
)
161 if (m_flag
& wxSHAPED
)
163 // adjust aspect ratio
164 int rwidth
= (int) (size
.y
* m_ratio
);
168 int rheight
= (int) (size
.x
/ m_ratio
);
169 // add vertical space
170 if (m_flag
& wxALIGN_CENTER_VERTICAL
)
171 pos
.y
+= (size
.y
- rheight
) / 2;
172 else if (m_flag
& wxALIGN_BOTTOM
)
173 pos
.y
+= (size
.y
- rheight
);
174 // use reduced dimensions
177 else if (rwidth
< size
.x
)
179 // add horizontal space
180 if (m_flag
& wxALIGN_CENTER_HORIZONTAL
)
181 pos
.x
+= (size
.x
- rwidth
) / 2;
182 else if (m_flag
& wxALIGN_RIGHT
)
183 pos
.x
+= (size
.x
- rwidth
);
188 // This is what GetPosition() returns. Since we calculate
189 // borders afterwards, GetPosition() will be the left/top
190 // corner of the surrounding border.
202 if (m_flag
& wxNORTH
)
207 if (m_flag
& wxSOUTH
)
213 m_sizer
->SetDimension( pos
.x
, pos
.y
, size
.x
, size
.y
);
216 m_window
->SetSize( pos
.x
, pos
.y
, size
.x
, size
.y
, wxSIZE_ALLOW_MINUS_ONE
);
221 void wxSizerItem::DeleteWindows()
227 m_sizer
->DeleteWindows();
230 bool wxSizerItem::IsWindow()
232 return (m_window
!= NULL
);
235 bool wxSizerItem::IsSizer()
237 return (m_sizer
!= NULL
);
240 bool wxSizerItem::IsSpacer()
242 return (m_window
== NULL
) && (m_sizer
== NULL
);
245 //---------------------------------------------------------------------------
247 //---------------------------------------------------------------------------
251 m_children
.DeleteContents( TRUE
);
261 void wxSizer::Add( wxWindow
*window
, int option
, int flag
, int border
, wxObject
* userData
)
263 m_children
.Append( new wxSizerItem( window
, option
, flag
, border
, userData
) );
264 window
->SetContainingSizer(this);
267 void wxSizer::Add( wxSizer
*sizer
, int option
, int flag
, int border
, wxObject
* userData
)
269 m_children
.Append( new wxSizerItem( sizer
, option
, flag
, border
, userData
) );
272 void wxSizer::Add( int width
, int height
, int option
, int flag
, int border
, wxObject
* userData
)
274 m_children
.Append( new wxSizerItem( width
, height
, option
, flag
, border
, userData
) );
277 void wxSizer::Prepend( wxWindow
*window
, int option
, int flag
, int border
, wxObject
* userData
)
279 m_children
.Insert( new wxSizerItem( window
, option
, flag
, border
, userData
) );
280 window
->SetContainingSizer(this);
283 void wxSizer::Prepend( wxSizer
*sizer
, int option
, int flag
, int border
, wxObject
* userData
)
285 m_children
.Insert( new wxSizerItem( sizer
, option
, flag
, border
, userData
) );
288 void wxSizer::Prepend( int width
, int height
, int option
, int flag
, int border
, wxObject
* userData
)
290 m_children
.Insert( new wxSizerItem( width
, height
, option
, flag
, border
, userData
) );
293 void wxSizer::Insert( int before
, wxWindow
*window
, int option
, int flag
, int border
, wxObject
* userData
)
295 m_children
.Insert( before
, new wxSizerItem( window
, option
, flag
, border
, userData
) );
296 window
->SetContainingSizer(this);
299 void wxSizer::Insert( int before
, wxSizer
*sizer
, int option
, int flag
, int border
, wxObject
* userData
)
301 m_children
.Insert( before
, new wxSizerItem( sizer
, option
, flag
, border
, userData
) );
304 void wxSizer::Insert( int before
, int width
, int height
, int option
, int flag
, int border
, wxObject
* userData
)
306 m_children
.Insert( before
, new wxSizerItem( width
, height
, option
, flag
, border
, userData
) );
309 bool wxSizer::Remove( wxWindow
*window
)
313 wxNode
*node
= m_children
.First();
316 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
317 if (item
->GetWindow() == window
)
319 item
->GetWindow()->SetContainingSizer(NULL
);
320 m_children
.DeleteNode( node
);
329 bool wxSizer::Remove( wxSizer
*sizer
)
333 wxNode
*node
= m_children
.First();
336 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
337 if (item
->GetSizer() == sizer
)
339 m_children
.DeleteNode( node
);
348 bool wxSizer::Remove( int pos
)
350 if ((size_t)pos
>= m_children
.GetCount())
352 wxNode
*node
= m_children
.Nth( pos
);
353 if (!node
) return FALSE
;
355 m_children
.DeleteNode( node
);
360 bool wxSizer::Detach( wxSizer
*sizer
)
364 wxNode
*node
= m_children
.First();
367 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
368 if (item
->GetSizer() == sizer
)
371 m_children
.DeleteNode( node
);
380 bool wxSizer::Detach( int pos
)
382 if ((size_t)pos
>= m_children
.GetCount())
384 wxNode
*node
= m_children
.Nth( pos
);
385 if (!node
) return FALSE
;
387 ( (wxSizerItem
*)node
->Data() )->DetachSizer();
388 m_children
.DeleteNode( node
);
393 void wxSizer::Clear( bool delete_windows
)
395 // First clear the ContainingSizer pointers
396 wxNode
*node
= m_children
.First();
399 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
400 if (item
->IsWindow())
401 item
->GetWindow()->SetContainingSizer(NULL
);
405 // Destroy the windows if needed
409 // Now empty the list
413 void wxSizer::DeleteWindows()
415 wxNode
*node
= m_children
.First();
418 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
419 item
->DeleteWindows();
424 wxSize
wxSizer::Fit( wxWindow
*window
)
427 if (window
->IsTopLevel())
428 size
= FitSize( window
);
430 size
= GetMinWindowSize( window
);
432 window
->SetSize( size
);
437 void wxSizer::FitInside( wxWindow
*window
)
440 if (window
->IsTopLevel())
441 size
= VirtualFitSize( window
);
443 size
= GetMinClientSize( window
);
445 window
->SetVirtualSize( size
);
448 void wxSizer::Layout()
454 void wxSizer::SetSizeHints( wxWindow
*window
)
456 // Preserve the window's max size hints, but set the
457 // lower bound according to the sizer calculations.
459 wxSize size
= Fit( window
);
461 window
->SetSizeHints( size
.x
,
463 window
->GetMaxWidth(),
464 window
->GetMaxHeight() );
467 void wxSizer::SetVirtualSizeHints( wxWindow
*window
)
469 // Preserve the window's max size hints, but set the
470 // lower bound according to the sizer calculations.
473 wxSize
size( window
->GetVirtualSize() );
474 window
->SetVirtualSizeHints( size
.x
,
476 window
->GetMaxWidth(),
477 window
->GetMaxHeight() );
480 wxSize
wxSizer::GetMaxWindowSize( wxWindow
*window
)
482 return window
->GetMaxSize();
485 wxSize
wxSizer::GetMinWindowSize( wxWindow
*window
)
487 wxSize
minSize( GetMinSize() );
488 wxSize
size( window
->GetSize() );
489 wxSize
client_size( window
->GetClientSize() );
490 return wxSize( minSize
.x
+size
.x
-client_size
.x
,
491 minSize
.y
+size
.y
-client_size
.y
);
494 // Return a window size that will fit within the screens dimensions
495 wxSize
wxSizer::FitSize( wxWindow
*window
)
497 wxSize size
= GetMinWindowSize( window
);
498 wxSize sizeMax
= GetMaxWindowSize( window
);
500 // Limit the size if sizeMax != wxDefaultSize
502 if ( size
.x
> sizeMax
.x
&& sizeMax
.x
!= -1 )
504 if ( size
.y
> sizeMax
.y
&& sizeMax
.y
!= -1 )
510 wxSize
wxSizer::GetMaxClientSize( wxWindow
*window
)
512 wxSize
maxSize( window
->GetMaxSize() );
514 if( maxSize
!= wxDefaultSize
)
516 wxSize
size( window
->GetSize() );
517 wxSize
client_size( window
->GetClientSize() );
519 return wxSize( maxSize
.x
+ client_size
.x
- size
.x
,
520 maxSize
.y
+ client_size
.y
- size
.y
);
523 return wxDefaultSize
;
526 wxSize
wxSizer::GetMinClientSize( wxWindow
*WXUNUSED(window
) )
528 return GetMinSize(); // Already returns client size.
531 wxSize
wxSizer::VirtualFitSize( wxWindow
*window
)
533 wxSize size
= GetMinClientSize( window
);
534 wxSize sizeMax
= GetMaxClientSize( window
);
536 // Limit the size if sizeMax != wxDefaultSize
538 if ( size
.x
> sizeMax
.x
&& sizeMax
.x
!= -1 )
540 if ( size
.y
> sizeMax
.y
&& sizeMax
.y
!= -1 )
546 void wxSizer::SetDimension( int x
, int y
, int width
, int height
)
555 wxSize
wxSizer::GetMinSize()
557 wxSize
ret( CalcMin() );
558 if (ret
.x
< m_minSize
.x
) ret
.x
= m_minSize
.x
;
559 if (ret
.y
< m_minSize
.y
) ret
.y
= m_minSize
.y
;
563 void wxSizer::DoSetMinSize( int width
, int height
)
566 m_minSize
.y
= height
;
569 bool wxSizer::DoSetItemMinSize( wxWindow
*window
, int width
, int height
)
573 wxNode
*node
= m_children
.First();
576 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
577 if (item
->GetWindow() == window
)
579 item
->SetInitSize( width
, height
);
585 node
= m_children
.First();
588 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
589 if (item
->GetSizer())
591 // It's a sizer, so lets search recursively.
592 if (item
->GetSizer()->DoSetItemMinSize( window
, width
, height
))
594 // A child sizer found the requested windw, exit.
604 bool wxSizer::DoSetItemMinSize( wxSizer
*sizer
, int width
, int height
)
608 wxNode
*node
= m_children
.First();
611 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
612 if (item
->GetSizer() == sizer
)
614 item
->GetSizer()->DoSetMinSize( width
, height
);
620 node
= m_children
.First();
623 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
624 if (item
->GetSizer())
626 // It's a sizer, so lets search recursively.
627 if (item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height
))
629 // A child sizer found the requested windw, exit.
639 bool wxSizer::DoSetItemMinSize( int pos
, int width
, int height
)
641 wxNode
*node
= m_children
.Nth( pos
);
642 if (!node
) return FALSE
;
644 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
645 if (item
->GetSizer())
647 // Sizers contains the minimal size in them, if not calculated ...
648 item
->GetSizer()->DoSetMinSize( width
, height
);
652 // ... but the minimal size of spacers and windows in stored in them
653 item
->SetInitSize( width
, height
);
659 void wxSizer::Show(wxWindow
*window
, bool show
)
661 wxNode
*node
= m_children
.GetFirst();
664 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
666 if (item
->IsWindow() && item
->GetWindow() == window
)
676 void wxSizer::Show(wxSizer
*sizer
, bool show
)
678 wxNode
*node
= m_children
.GetFirst();
681 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
683 if (item
->IsSizer() && item
->GetSizer() == sizer
)
686 sizer
->ShowItems(show
);
693 void wxSizer::ShowItems (bool show
)
695 wxNode
*node
= m_children
.GetFirst();
698 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
700 if (item
->IsWindow())
701 item
->GetWindow()->Show (show
);
702 else if (item
->IsSizer())
703 item
->GetSizer()->ShowItems (show
);
709 bool wxSizer::IsShown (wxWindow
*window
)
711 wxNode
*node
= m_children
.GetFirst();
714 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
716 if (item
->IsWindow() && item
->GetWindow() == window
)
718 return item
->IsShown();
726 bool wxSizer::IsShown (wxSizer
*sizer
)
728 wxNode
*node
= m_children
.GetFirst();
731 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
733 if (item
->IsSizer() && item
->GetSizer() == sizer
)
735 return item
->IsShown();
743 //---------------------------------------------------------------------------
745 //---------------------------------------------------------------------------
747 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap
)
755 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap
)
763 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const
765 int nitems
= m_children
.GetCount();
771 nrows
= (nitems
+ m_cols
- 1) / m_cols
;
775 ncols
= (nitems
+ m_rows
- 1) / m_rows
;
778 else // 0 columns, 0 rows?
780 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
789 void wxGridSizer::RecalcSizes()
791 int nitems
, nrows
, ncols
;
792 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
795 wxSize
sz( GetSize() );
796 wxPoint
pt( GetPosition() );
798 int w
= (sz
.x
- (ncols
- 1) * m_hgap
) / ncols
;
799 int h
= (sz
.y
- (nrows
- 1) * m_vgap
) / nrows
;
802 for (int c
= 0; c
< ncols
; c
++)
805 for (int r
= 0; r
< nrows
; r
++)
807 int i
= r
* ncols
+ c
;
810 wxNode
*node
= m_children
.Nth( i
);
813 SetItemBounds( (wxSizerItem
*) node
->Data(), x
, y
, w
, h
);
821 wxSize
wxGridSizer::CalcMin()
823 int nitems
, nrows
, ncols
;
824 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
825 return wxSize(10, 10);
827 // Find the max width and height for any component
831 wxNode
*node
= m_children
.First();
834 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
835 wxSize
sz( item
->CalcMin() );
836 w
= wxMax( w
, sz
.x
);
837 h
= wxMax( h
, sz
.y
);
842 return wxSize(ncols
* w
+ (ncols
-1) * m_hgap
,
843 nrows
* h
+ (nrows
-1) * m_vgap
);
846 void wxGridSizer::SetItemBounds( wxSizerItem
*item
, int x
, int y
, int w
, int h
)
849 wxSize
sz( item
->CalcMin() );
850 int flag
= item
->GetFlag();
852 if ((flag
& wxEXPAND
) || (flag
& wxSHAPED
))
858 if (flag
& wxALIGN_CENTER_HORIZONTAL
)
860 pt
.x
= x
+ (w
- sz
.x
) / 2;
862 else if (flag
& wxALIGN_RIGHT
)
864 pt
.x
= x
+ (w
- sz
.x
);
867 if (flag
& wxALIGN_CENTER_VERTICAL
)
869 pt
.y
= y
+ (h
- sz
.y
) / 2;
871 else if (flag
& wxALIGN_BOTTOM
)
873 pt
.y
= y
+ (h
- sz
.y
);
877 item
->SetDimension(pt
, sz
);
880 //---------------------------------------------------------------------------
882 //---------------------------------------------------------------------------
884 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap
)
885 : wxGridSizer( rows
, cols
, vgap
, hgap
)
887 m_rowHeights
= (int*) NULL
;
888 m_colWidths
= (int*) NULL
;
891 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap
)
892 : wxGridSizer( cols
, vgap
, hgap
)
894 m_rowHeights
= (int*) NULL
;
895 m_colWidths
= (int*) NULL
;
898 wxFlexGridSizer::~wxFlexGridSizer()
901 delete[] m_rowHeights
;
903 delete[] m_colWidths
;
906 void wxFlexGridSizer::CreateArrays()
909 delete[] m_rowHeights
;
911 delete[] m_colWidths
;
913 int nitems
, nrows
, ncols
;
914 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
920 m_rowHeights
= new int[nrows
];
921 m_colWidths
= new int[ncols
];
923 for (int col
= 0; col
< ncols
; col
++)
924 m_colWidths
[ col
] = 0;
925 for (int row
= 0; row
< nrows
; row
++)
926 m_rowHeights
[ row
] = 0;
929 void wxFlexGridSizer::RecalcSizes()
931 int nitems
, nrows
, ncols
;
932 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
935 wxSize
sz( GetSize() );
936 wxSize
minsz( CalcMin() );
937 wxPoint
pt( GetPosition() );
942 // Transfer only those rows into temp which exist in the sizer
943 // ignoring the superflouus ones. This prevents a segfault when
944 // calling AddGrowableRow( 3 ) if the sizer only has 2 rows.
945 for (idx
= 0; idx
< m_growableRows
.GetCount(); idx
++)
946 if (m_growableRows
[idx
] < nrows
)
947 temp
.Add( m_growableRows
[idx
] );
948 num
= temp
.GetCount();
950 if ((num
> 0) && (sz
.y
> minsz
.y
))
952 delta
= (sz
.y
- minsz
.y
) / num
;
953 for (idx
= 0; idx
< num
; idx
++)
954 m_rowHeights
[ temp
[idx
] ] += delta
;
959 for (idx
= 0; idx
< m_growableCols
.GetCount(); idx
++)
960 if (m_growableCols
[idx
] < ncols
)
961 temp
.Add( m_growableCols
[idx
] );
962 num
= temp
.GetCount();
964 if ((num
> 0) && (sz
.x
> minsz
.x
))
966 delta
= (sz
.x
- minsz
.x
) / num
;
967 for (idx
= 0; idx
< num
; idx
++)
968 m_colWidths
[ temp
[idx
] ] += delta
;
971 sz
= wxSize( pt
.x
+ sz
.x
, pt
.y
+ sz
.y
);
974 for (int c
= 0; c
< ncols
; c
++)
977 for (int r
= 0; r
< nrows
; r
++)
979 int i
= r
* ncols
+ c
;
982 wxNode
*node
= m_children
.Nth( i
);
985 int w
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x
- x
) );
986 int h
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y
- y
) );
988 SetItemBounds( (wxSizerItem
*) node
->Data(), x
, y
, w
, h
);
990 y
= y
+ m_rowHeights
[r
] + m_vgap
;
992 x
= x
+ m_colWidths
[c
] + m_hgap
;
996 wxSize
wxFlexGridSizer::CalcMin()
998 int nitems
, nrows
, ncols
;
999 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
1000 return wxSize(10,10);
1005 wxNode
*node
= m_children
.First();
1008 wxSizerItem
*item
= (wxSizerItem
*)node
->Data();
1009 wxSize
sz( item
->CalcMin() );
1010 int row
= i
/ ncols
;
1011 int col
= i
% ncols
;
1012 m_rowHeights
[ row
] = wxMax( sz
.y
, m_rowHeights
[ row
] );
1013 m_colWidths
[ col
] = wxMax( sz
.x
, m_colWidths
[ col
] );
1015 node
= node
->Next();
1020 for (int col
= 0; col
< ncols
; col
++)
1021 width
+= m_colWidths
[ col
];
1024 for (int row
= 0; row
< nrows
; row
++)
1025 height
+= m_rowHeights
[ row
];
1027 return wxSize( width
+ (ncols
-1) * m_hgap
,
1028 height
+ (nrows
-1) * m_vgap
);
1031 void wxFlexGridSizer::AddGrowableRow( size_t idx
)
1033 m_growableRows
.Add( idx
);
1036 void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx
) )
1040 void wxFlexGridSizer::AddGrowableCol( size_t idx
)
1042 m_growableCols
.Add( idx
);
1045 void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx
) )
1049 //---------------------------------------------------------------------------
1051 //---------------------------------------------------------------------------
1053 wxBoxSizer::wxBoxSizer( int orient
)
1058 void wxBoxSizer::RecalcSizes()
1060 if (m_children
.GetCount() == 0)
1067 if (m_orient
== wxHORIZONTAL
)
1069 delta
= (m_size
.x
- m_fixedWidth
) / m_stretchable
;
1070 extra
= (m_size
.x
- m_fixedWidth
) % m_stretchable
;
1074 delta
= (m_size
.y
- m_fixedHeight
) / m_stretchable
;
1075 extra
= (m_size
.y
- m_fixedHeight
) % m_stretchable
;
1079 wxPoint
pt( m_position
);
1081 wxNode
*node
= m_children
.GetFirst();
1084 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
1085 if (item
->IsShown())
1088 if (item
->GetOption())
1089 weight
= item
->GetOption();
1091 wxSize
size( item
->CalcMin() );
1093 if (m_orient
== wxVERTICAL
)
1095 wxCoord height
= size
.y
;
1096 if (item
->GetOption())
1098 height
= (delta
* weight
) + extra
;
1099 extra
= 0; // only the first item will get the remainder as extra size
1102 wxPoint
child_pos( pt
);
1103 wxSize
child_size( wxSize( size
.x
, height
) );
1105 if (item
->GetFlag() & (wxEXPAND
| wxSHAPED
))
1106 child_size
.x
= m_size
.x
;
1107 else if (item
->GetFlag() & wxALIGN_RIGHT
)
1108 child_pos
.x
+= m_size
.x
- size
.x
;
1109 else if (item
->GetFlag() & (wxCENTER
| wxALIGN_CENTER_HORIZONTAL
))
1110 // XXX wxCENTER is added for backward compatibility;
1111 // wxALIGN_CENTER should be used in new code
1112 child_pos
.x
+= (m_size
.x
- size
.x
) / 2;
1114 item
->SetDimension( child_pos
, child_size
);
1120 wxCoord width
= size
.x
;
1121 if (item
->GetOption())
1123 width
= (delta
* weight
) + extra
;
1124 extra
= 0; // only the first item will get the remainder as extra size
1127 wxPoint
child_pos( pt
);
1128 wxSize
child_size( wxSize(width
, size
.y
) );
1130 if (item
->GetFlag() & (wxEXPAND
| wxSHAPED
))
1131 child_size
.y
= m_size
.y
;
1132 else if (item
->GetFlag() & wxALIGN_BOTTOM
)
1133 child_pos
.y
+= m_size
.y
- size
.y
;
1134 else if (item
->GetFlag() & (wxCENTER
| wxALIGN_CENTER_VERTICAL
))
1135 // XXX wxCENTER is added for backward compatibility;
1136 // wxALIGN_CENTER should be used in new code
1137 child_pos
.y
+= (m_size
.y
- size
.y
) / 2;
1139 item
->SetDimension( child_pos
, child_size
);
1145 node
= node
->Next();
1149 wxSize
wxBoxSizer::CalcMin()
1151 if (m_children
.GetCount() == 0)
1152 return wxSize(10,10);
1160 // Find how long each stretch unit needs to be
1161 int stretchSize
= 1;
1162 wxNode
*node
= m_children
.GetFirst();
1165 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
1166 if (item
->IsShown() && item
->GetOption() != 0)
1168 int stretch
= item
->GetOption();
1169 wxSize
size( item
->CalcMin() );
1171 // Integer division rounded up is (a + b - 1) / b
1172 if (m_orient
== wxHORIZONTAL
)
1173 sizePerStretch
= ( size
.x
+ stretch
- 1 ) / stretch
;
1175 sizePerStretch
= ( size
.y
+ stretch
- 1 ) / stretch
;
1176 if (sizePerStretch
> stretchSize
)
1177 stretchSize
= sizePerStretch
;
1179 node
= node
->Next();
1181 // Calculate overall minimum size
1182 node
= m_children
.GetFirst();
1185 wxSizerItem
*item
= (wxSizerItem
*) node
->Data();
1186 if (item
->IsShown())
1188 m_stretchable
+= item
->GetOption();
1190 wxSize
size( item
->CalcMin() );
1191 if (item
->GetOption() != 0)
1193 if (m_orient
== wxHORIZONTAL
)
1194 size
.x
= stretchSize
* item
->GetOption();
1196 size
.y
= stretchSize
* item
->GetOption();
1199 if (m_orient
== wxHORIZONTAL
)
1201 m_minWidth
+= size
.x
;
1202 m_minHeight
= wxMax( m_minHeight
, size
.y
);
1206 m_minHeight
+= size
.y
;
1207 m_minWidth
= wxMax( m_minWidth
, size
.x
);
1210 if (item
->GetOption() == 0)
1212 if (m_orient
== wxVERTICAL
)
1214 m_fixedHeight
+= size
.y
;
1215 m_fixedWidth
= wxMax( m_fixedWidth
, size
.x
);
1219 m_fixedWidth
+= size
.x
;
1220 m_fixedHeight
= wxMax( m_fixedHeight
, size
.y
);
1224 node
= node
->Next();
1227 return wxSize( m_minWidth
, m_minHeight
);
1230 //---------------------------------------------------------------------------
1232 //---------------------------------------------------------------------------
1236 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox
*box
, int orient
)
1237 : wxBoxSizer( orient
)
1239 wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") );
1244 static void GetStaticBoxBorders(wxStaticBox
*box
,
1245 int *borderTop
, int *borderOther
)
1247 // this has to be done platform by platform as there is no way to
1248 // guess the thickness of a wxStaticBox border
1250 if ( box
->GetLabel().IsEmpty() )
1259 void wxStaticBoxSizer::RecalcSizes()
1261 int top_border
, other_border
;
1262 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1264 m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y
);
1266 wxPoint
old_pos( m_position
);
1267 m_position
.x
+= other_border
;
1268 m_position
.y
+= top_border
;
1269 wxSize
old_size( m_size
);
1270 m_size
.x
-= 2*other_border
;
1271 m_size
.y
-= top_border
+ other_border
;
1273 wxBoxSizer::RecalcSizes();
1275 m_position
= old_pos
;
1279 wxSize
wxStaticBoxSizer::CalcMin()
1281 int top_border
, other_border
;
1282 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1284 wxSize
ret( wxBoxSizer::CalcMin() );
1285 ret
.x
+= 2*other_border
;
1286 ret
.y
+= other_border
+ top_border
;
1291 #endif // wxUSE_STATBOX
1293 //---------------------------------------------------------------------------
1295 //---------------------------------------------------------------------------
1299 wxNotebookSizer::wxNotebookSizer( wxNotebook
*nb
)
1301 wxASSERT_MSG( nb
, wxT("wxNotebookSizer needs a notebook") );
1306 void wxNotebookSizer::RecalcSizes()
1308 m_notebook
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y
);
1311 wxSize
wxNotebookSizer::CalcMin()
1313 wxSize sizeBorder
= m_notebook
->CalcSizeFromPage(wxSize(0, 0));
1318 if (m_notebook
->GetChildren().GetCount() == 0)
1320 return wxSize(sizeBorder
.x
+ 10, sizeBorder
.y
+ 10);
1326 wxWindowList::Node
*node
= m_notebook
->GetChildren().GetFirst();
1329 wxWindow
*item
= node
->GetData();
1330 wxSizer
*itemsizer
= item
->GetSizer();
1334 wxSize
subsize( itemsizer
->CalcMin() );
1336 if (subsize
.x
> maxX
)
1338 if (subsize
.y
> maxY
)
1342 node
= node
->GetNext();
1345 return wxSize( maxX
, maxY
) + sizeBorder
;
1348 #endif // wxUSE_NOTEBOOK