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
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
14 #pragma implementation "sizer.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
26 #include "wx/statbox.h"
27 #include "wx/notebook.h"
28 #include <wx/listimpl.cpp>
30 //---------------------------------------------------------------------------
32 IMPLEMENT_ABSTRACT_CLASS(wxSizerItem
, wxObject
)
33 IMPLEMENT_ABSTRACT_CLASS(wxSizer
, wxObject
)
34 IMPLEMENT_ABSTRACT_CLASS(wxGridSizer
, wxSizer
)
35 IMPLEMENT_ABSTRACT_CLASS(wxFlexGridSizer
, wxGridSizer
)
36 IMPLEMENT_ABSTRACT_CLASS(wxBoxSizer
, wxSizer
)
38 IMPLEMENT_ABSTRACT_CLASS(wxStaticBoxSizer
, wxBoxSizer
)
41 IMPLEMENT_ABSTRACT_CLASS(wxNotebookSizer
, wxSizer
)
44 WX_DEFINE_EXPORTED_LIST( wxSizerItemList
);
47 //---------------------------------------------------------------------------
49 //---------------------------------------------------------------------------
51 wxSizerItem::wxSizerItem( int width
, int height
, int proportion
, int flag
, int border
, wxObject
* userData
)
54 , m_size( wxSize( width
, height
) ) // size is set directly
55 , m_minSize( m_size
) // minimal size is the initial size
56 , m_proportion( proportion
)
60 , m_userData( userData
)
65 wxSizerItem::wxSizerItem( wxWindow
*window
, int proportion
, int flag
, int border
, wxObject
* userData
)
68 , m_minSize( window
->GetSize() ) // minimal size is the initial size
69 , m_proportion( proportion
)
73 , m_userData( userData
)
75 // aspect ratio calculated from initial size
76 SetRatio( m_minSize
);
78 // m_size is calculated later
81 wxSizerItem::wxSizerItem( wxSizer
*sizer
, int proportion
, int flag
, int border
, wxObject
* userData
)
84 , m_proportion( proportion
)
89 , m_userData( userData
)
91 // m_minSize is calculated later
92 // m_size is calculated later
95 wxSizerItem::~wxSizerItem()
104 wxSize
wxSizerItem::GetSize()
108 ret
= m_sizer
->GetSize();
111 ret
= m_window
->GetSize();
118 if (m_flag
& wxNORTH
)
120 if (m_flag
& wxSOUTH
)
126 wxSize
wxSizerItem::CalcMin()
131 ret
= m_sizer
->GetMinSize();
133 // if we have to preserve aspect ratio _AND_ this is
134 // the first-time calculation, consider ret to be initial size
135 if ((m_flag
& wxSHAPED
) && !m_ratio
)
140 if ( IsWindow() && (m_flag
& wxADJUST_MINSIZE
) )
142 // By user request, keep the minimal size for this item
143 // in sync with the largest of BestSize and any user supplied
144 // minimum size hint. Useful in cases where the item is
145 // changeable -- static text labels, etc.
146 m_minSize
= m_window
->GetAdjustedBestSize();
156 if (m_flag
& wxNORTH
)
158 if (m_flag
& wxSOUTH
)
164 void wxSizerItem::SetDimension( wxPoint pos
, wxSize size
)
166 if (m_flag
& wxSHAPED
)
168 // adjust aspect ratio
169 int rwidth
= (int) (size
.y
* m_ratio
);
173 int rheight
= (int) (size
.x
/ m_ratio
);
174 // add vertical space
175 if (m_flag
& wxALIGN_CENTER_VERTICAL
)
176 pos
.y
+= (size
.y
- rheight
) / 2;
177 else if (m_flag
& wxALIGN_BOTTOM
)
178 pos
.y
+= (size
.y
- rheight
);
179 // use reduced dimensions
182 else if (rwidth
< size
.x
)
184 // add horizontal space
185 if (m_flag
& wxALIGN_CENTER_HORIZONTAL
)
186 pos
.x
+= (size
.x
- rwidth
) / 2;
187 else if (m_flag
& wxALIGN_RIGHT
)
188 pos
.x
+= (size
.x
- rwidth
);
193 // This is what GetPosition() returns. Since we calculate
194 // borders afterwards, GetPosition() will be the left/top
195 // corner of the surrounding border.
207 if (m_flag
& wxNORTH
)
212 if (m_flag
& wxSOUTH
)
218 m_sizer
->SetDimension( pos
.x
, pos
.y
, size
.x
, size
.y
);
221 m_window
->SetSize( pos
.x
, pos
.y
, size
.x
, size
.y
, wxSIZE_ALLOW_MINUS_ONE
);
226 void wxSizerItem::DeleteWindows()
232 m_sizer
->DeleteWindows();
235 bool wxSizerItem::IsWindow()
237 return (m_window
!= NULL
);
240 bool wxSizerItem::IsSizer()
242 return (m_sizer
!= NULL
);
245 bool wxSizerItem::IsSpacer()
247 return (m_window
== NULL
) && (m_sizer
== NULL
);
250 void wxSizerItem::Show( bool show
)
255 m_window
->Show( show
);
257 m_sizer
->ShowItems( show
);
259 // ... nothing else to do to hide/show spacers
262 void wxSizerItem::SetOption( int option
)
264 SetProportion( option
);
267 int wxSizerItem::GetOption() const
269 return GetProportion();
273 //---------------------------------------------------------------------------
275 //---------------------------------------------------------------------------
278 : m_minSize( wxSize( 0, 0 ) )
280 m_children
.DeleteContents( true );
288 void wxSizer::Add( wxWindow
*window
, int proportion
, int flag
, int border
, wxObject
* userData
)
290 m_children
.Append( new wxSizerItem( window
, proportion
, flag
, border
, userData
) );
291 window
->SetContainingSizer( this );
294 void wxSizer::Add( wxSizer
*sizer
, int proportion
, int flag
, int border
, wxObject
* userData
)
296 m_children
.Append( new wxSizerItem( sizer
, proportion
, flag
, border
, userData
) );
299 void wxSizer::Add( int width
, int height
, int proportion
, int flag
, int border
, wxObject
* userData
)
301 m_children
.Append( new wxSizerItem( width
, height
, proportion
, flag
, border
, userData
) );
304 void wxSizer::Add( wxSizerItem
*item
)
306 m_children
.Append( item
);
308 if( item
->GetWindow() )
309 item
->GetWindow()->SetContainingSizer( this );
312 void wxSizer::Prepend( wxWindow
*window
, int proportion
, int flag
, int border
, wxObject
* userData
)
314 m_children
.Insert( new wxSizerItem( window
, proportion
, flag
, border
, userData
) );
315 window
->SetContainingSizer( this );
318 void wxSizer::Prepend( wxSizer
*sizer
, int proportion
, int flag
, int border
, wxObject
* userData
)
320 m_children
.Insert( new wxSizerItem( sizer
, proportion
, flag
, border
, userData
) );
323 void wxSizer::Prepend( int width
, int height
, int proportion
, int flag
, int border
, wxObject
* userData
)
325 m_children
.Insert( new wxSizerItem( width
, height
, proportion
, flag
, border
, userData
) );
328 void wxSizer::Prepend( wxSizerItem
*item
)
330 m_children
.Insert( item
);
332 if( item
->GetWindow() )
333 item
->GetWindow()->SetContainingSizer( this );
336 void wxSizer::Insert( size_t index
,
343 m_children
.Insert( index
,
344 new wxSizerItem( window
, proportion
, flag
, border
, userData
) );
345 window
->SetContainingSizer( this );
348 void wxSizer::Insert( size_t index
,
355 m_children
.Insert( index
,
356 new wxSizerItem( sizer
, proportion
, flag
, border
, userData
) );
359 void wxSizer::Insert( size_t index
,
367 m_children
.Insert( index
,
368 new wxSizerItem( width
, height
, proportion
, flag
, border
, userData
) );
371 void wxSizer::Insert( size_t index
, wxSizerItem
*item
)
373 m_children
.Insert( index
, item
);
375 if( item
->GetWindow() )
376 item
->GetWindow()->SetContainingSizer( this );
379 bool wxSizer::Remove( wxWindow
*window
)
381 return Detach( window
);
384 bool wxSizer::Remove( wxSizer
*sizer
)
386 wxASSERT_MSG( sizer
, _T("Removing NULL sizer") );
388 wxSizerItemList::Node
*node
= m_children
.GetFirst();
391 wxSizerItem
*item
= node
->GetData();
393 if (item
->GetSizer() == sizer
)
394 return m_children
.DeleteNode( node
);
396 node
= node
->GetNext();
402 bool wxSizer::Remove( size_t index
)
404 wxCHECK_MSG( index
< m_children
.GetCount(),
406 _T("Remove index is out of range") );
408 wxSizerItemList::Node
*node
= m_children
.Item( index
);
410 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
412 return m_children
.DeleteNode( node
);
415 bool wxSizer::Detach( wxSizer
*sizer
)
417 wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") );
419 wxSizerItemList::Node
*node
= m_children
.GetFirst();
422 wxSizerItem
*item
= node
->GetData();
424 if (item
->GetSizer() == sizer
)
427 return m_children
.DeleteNode( node
);
429 node
= node
->GetNext();
435 bool wxSizer::Detach( wxWindow
*window
)
437 wxASSERT_MSG( window
, _T("Detaching NULL window") );
439 wxSizerItemList::Node
*node
= m_children
.GetFirst();
442 wxSizerItem
*item
= node
->GetData();
444 if (item
->GetWindow() == window
)
446 item
->GetWindow()->SetContainingSizer( NULL
);
447 return m_children
.DeleteNode( node
);
449 node
= node
->GetNext();
455 bool wxSizer::Detach( size_t index
)
457 wxCHECK_MSG( index
< m_children
.GetCount(),
459 _T("Detach index is out of range") );
461 wxSizerItemList::Node
*node
= m_children
.Item( index
);
463 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
465 node
->GetData()->DetachSizer();
467 return m_children
.DeleteNode( node
);
470 void wxSizer::Clear( bool delete_windows
)
472 // First clear the ContainingSizer pointers
473 wxSizerItemList::Node
*node
= m_children
.GetFirst();
476 wxSizerItem
*item
= node
->GetData();
478 if (item
->IsWindow())
479 item
->GetWindow()->SetContainingSizer( NULL
);
480 node
= node
->GetNext();
483 // Destroy the windows if needed
487 // Now empty the list
491 void wxSizer::DeleteWindows()
493 wxSizerItemList::Node
*node
= m_children
.GetFirst();
496 wxSizerItem
*item
= node
->GetData();
498 item
->DeleteWindows();
499 node
= node
->GetNext();
503 wxSize
wxSizer::Fit( wxWindow
*window
)
506 if (window
->IsTopLevel())
507 size
= FitSize( window
);
509 size
= GetMinWindowSize( window
);
511 window
->SetSize( size
);
516 void wxSizer::FitInside( wxWindow
*window
)
519 if (window
->IsTopLevel())
520 size
= VirtualFitSize( window
);
522 size
= GetMinClientSize( window
);
524 window
->SetVirtualSize( size
);
527 void wxSizer::Layout()
533 void wxSizer::SetSizeHints( wxWindow
*window
)
535 // Preserve the window's max size hints, but set the
536 // lower bound according to the sizer calculations.
538 wxSize size
= Fit( window
);
540 window
->SetSizeHints( size
.x
,
542 window
->GetMaxWidth(),
543 window
->GetMaxHeight() );
546 void wxSizer::SetVirtualSizeHints( wxWindow
*window
)
548 // Preserve the window's max size hints, but set the
549 // lower bound according to the sizer calculations.
552 wxSize
size( window
->GetVirtualSize() );
553 window
->SetVirtualSizeHints( size
.x
,
555 window
->GetMaxWidth(),
556 window
->GetMaxHeight() );
559 wxSize
wxSizer::GetMaxWindowSize( wxWindow
*window
)
561 return window
->GetMaxSize();
564 wxSize
wxSizer::GetMinWindowSize( wxWindow
*window
)
566 wxSize
minSize( GetMinSize() );
567 wxSize
size( window
->GetSize() );
568 wxSize
client_size( window
->GetClientSize() );
570 return wxSize( minSize
.x
+size
.x
-client_size
.x
,
571 minSize
.y
+size
.y
-client_size
.y
);
574 // Return a window size that will fit within the screens dimensions
575 wxSize
wxSizer::FitSize( wxWindow
*window
)
577 wxSize size
= GetMinWindowSize( window
);
578 wxSize sizeMax
= GetMaxWindowSize( window
);
580 // Limit the size if sizeMax != wxDefaultSize
582 if ( size
.x
> sizeMax
.x
&& sizeMax
.x
!= -1 )
584 if ( size
.y
> sizeMax
.y
&& sizeMax
.y
!= -1 )
590 wxSize
wxSizer::GetMaxClientSize( wxWindow
*window
)
592 wxSize
maxSize( window
->GetMaxSize() );
594 if( maxSize
!= wxDefaultSize
)
596 wxSize
size( window
->GetSize() );
597 wxSize
client_size( window
->GetClientSize() );
599 return wxSize( maxSize
.x
+ client_size
.x
- size
.x
,
600 maxSize
.y
+ client_size
.y
- size
.y
);
603 return wxDefaultSize
;
606 wxSize
wxSizer::GetMinClientSize( wxWindow
*WXUNUSED(window
) )
608 return GetMinSize(); // Already returns client size.
611 wxSize
wxSizer::VirtualFitSize( wxWindow
*window
)
613 wxSize size
= GetMinClientSize( window
);
614 wxSize sizeMax
= GetMaxClientSize( window
);
616 // Limit the size if sizeMax != wxDefaultSize
618 if ( size
.x
> sizeMax
.x
&& sizeMax
.x
!= -1 )
620 if ( size
.y
> sizeMax
.y
&& sizeMax
.y
!= -1 )
626 void wxSizer::SetDimension( int x
, int y
, int width
, int height
)
635 wxSize
wxSizer::GetMinSize()
637 wxSize
ret( CalcMin() );
638 if (ret
.x
< m_minSize
.x
) ret
.x
= m_minSize
.x
;
639 if (ret
.y
< m_minSize
.y
) ret
.y
= m_minSize
.y
;
643 void wxSizer::DoSetMinSize( int width
, int height
)
646 m_minSize
.y
= height
;
649 bool wxSizer::DoSetItemMinSize( wxWindow
*window
, int width
, int height
)
651 wxASSERT_MSG( window
, _T("SetMinSize for NULL window") );
653 // Is it our immediate child?
655 wxSizerItemList::Node
*node
= m_children
.GetFirst();
658 wxSizerItem
*item
= node
->GetData();
660 if (item
->GetWindow() == window
)
662 item
->SetInitSize( width
, height
);
665 node
= node
->GetNext();
668 // No? Search any subsizers we own then
670 node
= m_children
.GetFirst();
673 wxSizerItem
*item
= node
->GetData();
675 if ( item
->GetSizer() &&
676 item
->GetSizer()->DoSetItemMinSize( window
, width
, height
) )
678 // A child sizer found the requested windw, exit.
681 node
= node
->GetNext();
687 bool wxSizer::DoSetItemMinSize( wxSizer
*sizer
, int width
, int height
)
689 wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") );
691 // Is it our immediate child?
693 wxSizerItemList::Node
*node
= m_children
.GetFirst();
696 wxSizerItem
*item
= node
->GetData();
698 if (item
->GetSizer() == sizer
)
700 item
->GetSizer()->DoSetMinSize( width
, height
);
703 node
= node
->GetNext();
706 // No? Search any subsizers we own then
708 node
= m_children
.GetFirst();
711 wxSizerItem
*item
= node
->GetData();
713 if ( item
->GetSizer() &&
714 item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height
) )
716 // A child found the requested sizer, exit.
719 node
= node
->GetNext();
725 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height
)
727 wxSizerItemList::Node
*node
= m_children
.Item( index
);
729 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
731 wxSizerItem
*item
= node
->GetData();
733 if (item
->GetSizer())
735 // Sizers contains the minimal size in them, if not calculated ...
736 item
->GetSizer()->DoSetMinSize( width
, height
);
740 // ... but the minimal size of spacers and windows in stored in them
741 item
->SetInitSize( width
, height
);
747 void wxSizer::Show( wxWindow
*window
, bool show
)
749 wxASSERT_MSG( window
, _T("Show for NULL window") );
751 wxSizerItemList::Node
*node
= m_children
.GetFirst();
754 wxSizerItem
*item
= node
->GetData();
756 if (item
->GetWindow() == window
)
761 node
= node
->GetNext();
765 void wxSizer::Show( wxSizer
*sizer
, bool show
)
767 wxASSERT_MSG( sizer
, _T("Show for NULL sizer") );
769 wxSizerItemList::Node
*node
= m_children
.GetFirst();
772 wxSizerItem
*item
= node
->GetData();
774 if (item
->GetSizer() == sizer
)
779 node
= node
->GetNext();
783 void wxSizer::Show( size_t index
, bool show
)
785 wxCHECK_RET( index
< m_children
.GetCount(),
786 _T("Show index is out of range") );
788 m_children
.Item( index
)->GetData()->Show( show
);
791 void wxSizer::ShowItems( bool show
)
793 wxSizerItemList::Node
*node
= m_children
.GetFirst();
796 node
->GetData()->Show( show
);
797 node
= node
->GetNext();
801 bool wxSizer::IsShown( wxWindow
*window
)
803 wxSizerItemList::Node
*node
= m_children
.GetFirst();
806 wxSizerItem
*item
= node
->GetData();
808 if (item
->GetWindow() == window
)
810 return item
->IsShown();
812 node
= node
->GetNext();
815 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
820 bool wxSizer::IsShown( wxSizer
*sizer
)
822 wxSizerItemList::Node
*node
= m_children
.GetFirst();
825 wxSizerItem
*item
= node
->GetData();
827 if (item
->GetSizer() == sizer
)
829 return item
->IsShown();
831 node
= node
->GetNext();
834 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
839 bool wxSizer::IsShown( size_t index
)
841 wxCHECK_MSG( index
< m_children
.GetCount(),
843 _T("IsShown index is out of range") );
845 return m_children
.Item( index
)->GetData()->IsShown();
849 //---------------------------------------------------------------------------
851 //---------------------------------------------------------------------------
853 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap
)
861 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap
)
869 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const
871 int nitems
= m_children
.GetCount();
877 nrows
= (nitems
+ m_cols
- 1) / m_cols
;
881 ncols
= (nitems
+ m_rows
- 1) / m_rows
;
884 else // 0 columns, 0 rows?
886 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
895 void wxGridSizer::RecalcSizes()
897 int nitems
, nrows
, ncols
;
898 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
901 wxSize
sz( GetSize() );
902 wxPoint
pt( GetPosition() );
904 int w
= (sz
.x
- (ncols
- 1) * m_hgap
) / ncols
;
905 int h
= (sz
.y
- (nrows
- 1) * m_vgap
) / nrows
;
908 for (int c
= 0; c
< ncols
; c
++)
911 for (int r
= 0; r
< nrows
; r
++)
913 int i
= r
* ncols
+ c
;
916 wxSizerItemList::Node
*node
= m_children
.Item( i
);
918 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") );
920 SetItemBounds( node
->GetData(), x
, y
, w
, h
);
928 wxSize
wxGridSizer::CalcMin()
930 int nitems
, nrows
, ncols
;
931 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
932 return wxSize(10, 10);
934 // Find the max width and height for any component
938 wxSizerItemList::Node
*node
= m_children
.GetFirst();
941 wxSizerItem
*item
= node
->GetData();
942 wxSize
sz( item
->CalcMin() );
944 w
= wxMax( w
, sz
.x
);
945 h
= wxMax( h
, sz
.y
);
947 node
= node
->GetNext();
950 return wxSize( ncols
* w
+ (ncols
-1) * m_hgap
,
951 nrows
* h
+ (nrows
-1) * m_vgap
);
954 void wxGridSizer::SetItemBounds( wxSizerItem
*item
, int x
, int y
, int w
, int h
)
957 wxSize
sz( item
->CalcMin() );
958 int flag
= item
->GetFlag();
960 if ((flag
& wxEXPAND
) || (flag
& wxSHAPED
))
966 if (flag
& wxALIGN_CENTER_HORIZONTAL
)
968 pt
.x
= x
+ (w
- sz
.x
) / 2;
970 else if (flag
& wxALIGN_RIGHT
)
972 pt
.x
= x
+ (w
- sz
.x
);
975 if (flag
& wxALIGN_CENTER_VERTICAL
)
977 pt
.y
= y
+ (h
- sz
.y
) / 2;
979 else if (flag
& wxALIGN_BOTTOM
)
981 pt
.y
= y
+ (h
- sz
.y
);
985 item
->SetDimension(pt
, sz
);
988 //---------------------------------------------------------------------------
990 //---------------------------------------------------------------------------
992 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap
)
993 : wxGridSizer( rows
, cols
, vgap
, hgap
)
994 , m_rowHeights( NULL
)
995 , m_colWidths( NULL
)
999 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap
)
1000 : wxGridSizer( cols
, vgap
, hgap
)
1001 , m_rowHeights( NULL
)
1002 , m_colWidths( NULL
)
1006 wxFlexGridSizer::~wxFlexGridSizer()
1009 delete[] m_rowHeights
;
1011 delete[] m_colWidths
;
1014 void wxFlexGridSizer::CreateArrays()
1017 delete[] m_rowHeights
;
1019 delete[] m_colWidths
;
1021 int nitems
, nrows
, ncols
;
1022 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
1028 m_rowHeights
= new int[nrows
];
1029 m_colWidths
= new int[ncols
];
1031 for (int col
= 0; col
< ncols
; col
++)
1032 m_colWidths
[ col
] = 0;
1033 for (int row
= 0; row
< nrows
; row
++)
1034 m_rowHeights
[ row
] = 0;
1037 void wxFlexGridSizer::RecalcSizes()
1039 int nitems
, nrows
, ncols
;
1040 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
1043 wxSize
sz( GetSize() );
1044 wxSize
minsz( CalcMin() );
1045 wxPoint
pt( GetPosition() );
1050 // Transfer only those rows into temp which exist in the sizer
1051 // ignoring the superflouus ones. This prevents a segfault when
1052 // calling AddGrowableRow( 3 ) if the sizer only has 2 rows.
1053 for (idx
= 0; idx
< m_growableRows
.GetCount(); idx
++)
1054 if (m_growableRows
[idx
] < nrows
)
1055 temp
.Add( m_growableRows
[idx
] );
1056 num
= temp
.GetCount();
1058 if ((num
> 0) && (sz
.y
> minsz
.y
))
1060 delta
= (sz
.y
- minsz
.y
) / num
;
1061 for (idx
= 0; idx
< num
; idx
++)
1062 m_rowHeights
[ temp
[idx
] ] += delta
;
1067 for (idx
= 0; idx
< m_growableCols
.GetCount(); idx
++)
1068 if (m_growableCols
[idx
] < ncols
)
1069 temp
.Add( m_growableCols
[idx
] );
1070 num
= temp
.GetCount();
1072 if ((num
> 0) && (sz
.x
> minsz
.x
))
1074 delta
= (sz
.x
- minsz
.x
) / num
;
1075 for (idx
= 0; idx
< num
; idx
++)
1076 m_colWidths
[ temp
[idx
] ] += delta
;
1079 sz
= wxSize( pt
.x
+ sz
.x
, pt
.y
+ sz
.y
);
1082 for (int c
= 0; c
< ncols
; c
++)
1085 for (int r
= 0; r
< nrows
; r
++)
1087 int i
= r
* ncols
+ c
;
1090 wxSizerItemList::Node
*node
= m_children
.Item( i
);
1092 wxASSERT_MSG( node
, _T("Failed to find node") );
1094 int w
= wxMax( 0, wxMin( m_colWidths
[c
], sz
.x
- x
) );
1095 int h
= wxMax( 0, wxMin( m_rowHeights
[r
], sz
.y
- y
) );
1097 SetItemBounds( node
->GetData(), x
, y
, w
, h
);
1099 y
= y
+ m_rowHeights
[r
] + m_vgap
;
1101 x
= x
+ m_colWidths
[c
] + m_hgap
;
1105 wxSize
wxFlexGridSizer::CalcMin()
1107 int nitems
, nrows
, ncols
;
1108 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
1109 return wxSize(10,10);
1114 wxSizerItemList::Node
*node
= m_children
.GetFirst();
1118 wxSizerItem
*item
= node
->GetData();
1119 wxSize
sz( item
->CalcMin() );
1120 int row
= i
/ ncols
;
1121 int col
= i
% ncols
;
1123 m_rowHeights
[ row
] = wxMax( sz
.y
, m_rowHeights
[ row
] );
1124 m_colWidths
[ col
] = wxMax( sz
.x
, m_colWidths
[ col
] );
1126 node
= node
->GetNext();
1131 for (int col
= 0; col
< ncols
; col
++)
1132 width
+= m_colWidths
[ col
];
1135 for (int row
= 0; row
< nrows
; row
++)
1136 height
+= m_rowHeights
[ row
];
1138 return wxSize( width
+ (ncols
-1) * m_hgap
,
1139 height
+ (nrows
-1) * m_vgap
);
1142 void wxFlexGridSizer::AddGrowableRow( size_t idx
)
1144 m_growableRows
.Add( idx
);
1147 void wxFlexGridSizer::RemoveGrowableRow( size_t WXUNUSED(idx
) )
1151 void wxFlexGridSizer::AddGrowableCol( size_t idx
)
1153 m_growableCols
.Add( idx
);
1156 void wxFlexGridSizer::RemoveGrowableCol( size_t WXUNUSED(idx
) )
1160 //---------------------------------------------------------------------------
1162 //---------------------------------------------------------------------------
1164 wxBoxSizer::wxBoxSizer( int orient
)
1165 : m_orient( orient
)
1169 void wxBoxSizer::RecalcSizes()
1171 if (m_children
.GetCount() == 0)
1178 if (m_orient
== wxHORIZONTAL
)
1180 delta
= (m_size
.x
- m_fixedWidth
) / m_stretchable
;
1181 extra
= (m_size
.x
- m_fixedWidth
) % m_stretchable
;
1185 delta
= (m_size
.y
- m_fixedHeight
) / m_stretchable
;
1186 extra
= (m_size
.y
- m_fixedHeight
) % m_stretchable
;
1190 wxPoint
pt( m_position
);
1192 wxSizerItemList::Node
*node
= m_children
.GetFirst();
1195 wxSizerItem
*item
= node
->GetData();
1197 if (item
->IsShown())
1200 if (item
->GetProportion())
1201 weight
= item
->GetProportion();
1203 wxSize
size( item
->CalcMin() );
1205 if (m_orient
== wxVERTICAL
)
1207 wxCoord height
= size
.y
;
1208 if (item
->GetProportion())
1210 height
= (delta
* weight
) + extra
;
1211 extra
= 0; // only the first item will get the remainder as extra size
1214 wxPoint
child_pos( pt
);
1215 wxSize
child_size( wxSize( size
.x
, height
) );
1217 if (item
->GetFlag() & (wxEXPAND
| wxSHAPED
))
1218 child_size
.x
= m_size
.x
;
1219 else if (item
->GetFlag() & wxALIGN_RIGHT
)
1220 child_pos
.x
+= m_size
.x
- size
.x
;
1221 else if (item
->GetFlag() & (wxCENTER
| wxALIGN_CENTER_HORIZONTAL
))
1222 // XXX wxCENTER is added for backward compatibility;
1223 // wxALIGN_CENTER should be used in new code
1224 child_pos
.x
+= (m_size
.x
- size
.x
) / 2;
1226 item
->SetDimension( child_pos
, child_size
);
1232 wxCoord width
= size
.x
;
1233 if (item
->GetProportion())
1235 width
= (delta
* weight
) + extra
;
1236 extra
= 0; // only the first item will get the remainder as extra size
1239 wxPoint
child_pos( pt
);
1240 wxSize
child_size( wxSize(width
, size
.y
) );
1242 if (item
->GetFlag() & (wxEXPAND
| wxSHAPED
))
1243 child_size
.y
= m_size
.y
;
1244 else if (item
->GetFlag() & wxALIGN_BOTTOM
)
1245 child_pos
.y
+= m_size
.y
- size
.y
;
1246 else if (item
->GetFlag() & (wxCENTER
| wxALIGN_CENTER_VERTICAL
))
1247 // XXX wxCENTER is added for backward compatibility;
1248 // wxALIGN_CENTER should be used in new code
1249 child_pos
.y
+= (m_size
.y
- size
.y
) / 2;
1251 item
->SetDimension( child_pos
, child_size
);
1257 node
= node
->GetNext();
1261 wxSize
wxBoxSizer::CalcMin()
1263 if (m_children
.GetCount() == 0)
1264 return wxSize(10,10);
1272 // Find how long each stretch unit needs to be
1273 int stretchSize
= 1;
1274 wxSizerItemList::Node
*node
= m_children
.GetFirst();
1278 wxSizerItem
*item
= node
->GetData();
1280 if (item
->IsShown() && item
->GetProportion() != 0)
1282 int stretch
= item
->GetProportion();
1283 wxSize
size( item
->CalcMin() );
1285 // Integer division rounded up is (a + b - 1) / b
1286 if (m_orient
== wxHORIZONTAL
)
1287 sizePerStretch
= ( size
.x
+ stretch
- 1 ) / stretch
;
1289 sizePerStretch
= ( size
.y
+ stretch
- 1 ) / stretch
;
1290 if (sizePerStretch
> stretchSize
)
1291 stretchSize
= sizePerStretch
;
1293 node
= node
->GetNext();
1296 // Calculate overall minimum size
1297 node
= m_children
.GetFirst();
1300 wxSizerItem
*item
= node
->GetData();
1302 if (item
->IsShown())
1304 m_stretchable
+= item
->GetProportion();
1306 wxSize
size( item
->CalcMin() );
1307 if (item
->GetProportion() != 0)
1309 if (m_orient
== wxHORIZONTAL
)
1310 size
.x
= stretchSize
* item
->GetProportion();
1312 size
.y
= stretchSize
* item
->GetProportion();
1315 if (m_orient
== wxHORIZONTAL
)
1317 m_minWidth
+= size
.x
;
1318 m_minHeight
= wxMax( m_minHeight
, size
.y
);
1322 m_minHeight
+= size
.y
;
1323 m_minWidth
= wxMax( m_minWidth
, size
.x
);
1326 if (item
->GetProportion() == 0)
1328 if (m_orient
== wxVERTICAL
)
1330 m_fixedHeight
+= size
.y
;
1331 m_fixedWidth
= wxMax( m_fixedWidth
, size
.x
);
1335 m_fixedWidth
+= size
.x
;
1336 m_fixedHeight
= wxMax( m_fixedHeight
, size
.y
);
1340 node
= node
->GetNext();
1343 return wxSize( m_minWidth
, m_minHeight
);
1346 //---------------------------------------------------------------------------
1348 //---------------------------------------------------------------------------
1352 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox
*box
, int orient
)
1353 : wxBoxSizer( orient
)
1354 , m_staticBox( box
)
1356 wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") );
1359 static void GetStaticBoxBorders( wxStaticBox
*box
,
1363 // this has to be done platform by platform as there is no way to
1364 // guess the thickness of a wxStaticBox border
1366 if ( box
->GetLabel().IsEmpty() )
1375 void wxStaticBoxSizer::RecalcSizes()
1377 int top_border
, other_border
;
1378 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1380 m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y
);
1382 wxPoint
old_pos( m_position
);
1383 m_position
.x
+= other_border
;
1384 m_position
.y
+= top_border
;
1385 wxSize
old_size( m_size
);
1386 m_size
.x
-= 2*other_border
;
1387 m_size
.y
-= top_border
+ other_border
;
1389 wxBoxSizer::RecalcSizes();
1391 m_position
= old_pos
;
1395 wxSize
wxStaticBoxSizer::CalcMin()
1397 int top_border
, other_border
;
1398 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1400 wxSize
ret( wxBoxSizer::CalcMin() );
1401 ret
.x
+= 2*other_border
;
1402 ret
.y
+= other_border
+ top_border
;
1407 #endif // wxUSE_STATBOX
1409 //---------------------------------------------------------------------------
1411 //---------------------------------------------------------------------------
1415 wxNotebookSizer::wxNotebookSizer( wxNotebook
*nb
)
1418 wxASSERT_MSG( nb
, wxT("wxNotebookSizer needs a notebook") );
1421 void wxNotebookSizer::RecalcSizes()
1423 m_notebook
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y
);
1426 wxSize
wxNotebookSizer::CalcMin()
1428 wxSize sizeBorder
= m_notebook
->CalcSizeFromPage(wxSize(0, 0));
1433 if (m_notebook
->GetChildren().GetCount() == 0)
1435 return wxSize(sizeBorder
.x
+ 10, sizeBorder
.y
+ 10);
1441 wxWindowList::Node
*node
= m_notebook
->GetChildren().GetFirst();
1444 wxWindow
*item
= node
->GetData();
1445 wxSizer
*itemsizer
= item
->GetSizer();
1449 wxSize
subsize( itemsizer
->CalcMin() );
1451 if (subsize
.x
> maxX
)
1453 if (subsize
.y
> maxY
)
1457 node
= node
->GetNext();
1460 return wxSize( maxX
, maxY
) + sizeBorder
;
1463 #endif // wxUSE_NOTEBOOK