1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/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
9 // Copyright: (c) Robin Dunn, Robert Roebling
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
23 #include "wx/string.h"
27 #include "wx/settings.h"
28 #include "wx/button.h"
29 #include "wx/statbox.h"
30 #include "wx/toplevel.h"
33 #include "wx/listimpl.cpp"
35 #if WXWIN_COMPATIBILITY_2_4
36 #include "wx/notebook.h"
39 //---------------------------------------------------------------------------
41 IMPLEMENT_CLASS(wxSizerItem, wxObject)
42 IMPLEMENT_CLASS(wxSizer, wxObject)
43 IMPLEMENT_CLASS(wxGridSizer, wxSizer)
44 IMPLEMENT_CLASS(wxFlexGridSizer, wxGridSizer)
45 IMPLEMENT_CLASS(wxBoxSizer, wxSizer)
47 IMPLEMENT_CLASS(wxStaticBoxSizer, wxBoxSizer)
50 IMPLEMENT_CLASS(wxStdDialogButtonSizer, wxBoxSizer)
53 WX_DEFINE_EXPORTED_LIST( wxSizerItemList )
88 // ----------------------------------------------------------------------------
90 // ----------------------------------------------------------------------------
92 void wxSizerItem::Init(const wxSizerFlags& flags)
96 m_proportion = flags.GetProportion();
97 m_flag = flags.GetFlags();
98 m_border = flags.GetBorderInPixels();
101 wxSizerItem::wxSizerItem()
113 void wxSizerItem::SetWindow(wxWindow *window)
115 wxCHECK_RET( window, _T("NULL window in wxSizerItem::SetWindow()") );
117 m_kind = Item_Window;
120 // window doesn't become smaller than its initial size, whatever happens
121 m_minSize = window->GetSize();
123 if ( m_flag & wxFIXED_MINSIZE )
124 window->SetMinSize(m_minSize);
126 // aspect ratio calculated from initial size
130 wxSizerItem::wxSizerItem(wxWindow *window,
135 : m_proportion(proportion),
144 void wxSizerItem::SetSizer(wxSizer *sizer)
150 wxSizerItem::wxSizerItem(wxSizer *sizer,
155 : m_proportion(proportion),
163 // m_minSize is set later
167 void wxSizerItem::SetSpacer(const wxSize& size)
169 m_kind = Item_Spacer;
170 m_spacer = new wxSizerSpacer(size);
175 wxSizerItem::wxSizerItem(int width,
181 : m_minSize(width, height), // minimal size is the initial size
182 m_proportion(proportion),
187 SetSpacer(width, height);
190 wxSizerItem::~wxSizerItem()
200 m_window->SetContainingSizer(NULL);
213 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
217 wxSize wxSizerItem::GetSpacer() const
220 if ( m_kind == Item_Spacer )
221 size = m_spacer->GetSize();
227 wxSize wxSizerItem::GetSize() const
236 ret = m_window->GetSize();
240 ret = m_sizer->GetSize();
244 ret = m_spacer->GetSize();
249 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
256 if (m_flag & wxNORTH)
258 if (m_flag & wxSOUTH)
264 wxSize wxSizerItem::CalcMin()
268 m_minSize = m_sizer->GetMinSize();
270 // if we have to preserve aspect ratio _AND_ this is
271 // the first-time calculation, consider ret to be initial size
272 if ( (m_flag & wxSHAPED) && wxIsNullDouble(m_ratio) )
275 else if ( IsWindow() )
277 // Since the size of the window may change during runtime, we
278 // should use the current minimal/best size.
279 m_minSize = m_window->GetBestFittingSize();
282 return GetMinSizeWithBorder();
285 wxSize wxSizerItem::GetMinSizeWithBorder() const
287 wxSize ret = m_minSize;
293 if (m_flag & wxNORTH)
295 if (m_flag & wxSOUTH)
302 void wxSizerItem::SetDimension( const wxPoint& pos_, const wxSize& size_ )
306 if (m_flag & wxSHAPED)
308 // adjust aspect ratio
309 int rwidth = (int) (size.y * m_ratio);
313 int rheight = (int) (size.x / m_ratio);
314 // add vertical space
315 if (m_flag & wxALIGN_CENTER_VERTICAL)
316 pos.y += (size.y - rheight) / 2;
317 else if (m_flag & wxALIGN_BOTTOM)
318 pos.y += (size.y - rheight);
319 // use reduced dimensions
322 else if (rwidth < size.x)
324 // add horizontal space
325 if (m_flag & wxALIGN_CENTER_HORIZONTAL)
326 pos.x += (size.x - rwidth) / 2;
327 else if (m_flag & wxALIGN_RIGHT)
328 pos.x += (size.x - rwidth);
333 // This is what GetPosition() returns. Since we calculate
334 // borders afterwards, GetPosition() will be the left/top
335 // corner of the surrounding border.
347 if (m_flag & wxNORTH)
352 if (m_flag & wxSOUTH)
362 m_rect = wxRect(pos, size);
367 wxFAIL_MSG( _T("can't set size of uninitialized sizer item") );
371 m_window->SetSize(pos.x, pos.y, size.x, size.y,
372 wxSIZE_ALLOW_MINUS_ONE);
376 m_sizer->SetDimension(pos.x, pos.y, size.x, size.y);
380 m_spacer->SetSize(size);
385 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
389 void wxSizerItem::DeleteWindows()
398 //We are deleting the window from this sizer - normally
399 //the window destroys the sizer associated with it,
400 //which might destroy this, which we don't want
401 m_window->SetContainingSizer(NULL);
403 //Putting this after the switch will result in a spacer
404 //not being deleted properly on destruction
409 m_sizer->DeleteWindows();
414 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
419 void wxSizerItem::Show( bool show )
424 wxFAIL_MSG( _T("can't show uninitialized sizer item") );
428 m_window->Show(show);
436 m_spacer->Show(show);
441 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
445 bool wxSizerItem::IsShown() const
450 // we may be called from CalcMin(), just return false so that we're
455 return m_window->IsShown();
458 // arbitrarily decide that if at least one of our elements is
459 // shown, so are we (this arbitrariness is the reason for
460 // deprecating this function)
462 for ( wxSizerItemList::compatibility_iterator
463 node = m_sizer->GetChildren().GetFirst();
465 node = node->GetNext() )
467 if ( node->GetData()->IsShown() )
474 return m_spacer->IsShown();
478 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
484 #if WXWIN_COMPATIBILITY_2_6
485 void wxSizerItem::SetOption( int option )
487 SetProportion( option );
490 int wxSizerItem::GetOption() const
492 return GetProportion();
494 #endif // WXWIN_COMPATIBILITY_2_6
497 //---------------------------------------------------------------------------
499 //---------------------------------------------------------------------------
503 WX_CLEAR_LIST(wxSizerItemList, m_children);
506 wxSizerItem* wxSizer::Insert( size_t index, wxSizerItem *item )
508 m_children.Insert( index, item );
510 if ( item->GetWindow() )
511 item->GetWindow()->SetContainingSizer( this );
516 void wxSizer::SetContainingWindow(wxWindow *win)
518 if ( win == m_containingWindow )
521 m_containingWindow = win;
523 // set the same window for all nested sizers as well, they also are in the
525 for ( wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
527 node = node->GetNext() )
529 wxSizerItem *const item = node->GetData();
530 wxSizer *const sizer = item->GetSizer();
534 sizer->SetContainingWindow(win);
539 #if WXWIN_COMPATIBILITY_2_6
540 bool wxSizer::Remove( wxWindow *window )
542 return Detach( window );
544 #endif // WXWIN_COMPATIBILITY_2_6
546 bool wxSizer::Remove( wxSizer *sizer )
548 wxASSERT_MSG( sizer, _T("Removing NULL sizer") );
550 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
553 wxSizerItem *item = node->GetData();
555 if (item->GetSizer() == sizer)
558 m_children.Erase( node );
562 node = node->GetNext();
568 bool wxSizer::Remove( int index )
570 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
572 _T("Remove index is out of range") );
574 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
576 wxCHECK_MSG( node, false, _T("Failed to find child node") );
578 wxSizerItem *item = node->GetData();
580 if ( item->IsWindow() )
581 item->GetWindow()->SetContainingSizer( NULL );
584 m_children.Erase( node );
588 bool wxSizer::Detach( wxSizer *sizer )
590 wxASSERT_MSG( sizer, _T("Detaching NULL sizer") );
592 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
595 wxSizerItem *item = node->GetData();
597 if (item->GetSizer() == sizer)
601 m_children.Erase( node );
604 node = node->GetNext();
610 bool wxSizer::Detach( wxWindow *window )
612 wxASSERT_MSG( window, _T("Detaching NULL window") );
614 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
617 wxSizerItem *item = node->GetData();
619 if (item->GetWindow() == window)
621 item->GetWindow()->SetContainingSizer( NULL );
623 m_children.Erase( node );
626 node = node->GetNext();
632 bool wxSizer::Detach( int index )
634 wxCHECK_MSG( index >= 0 && (size_t)index < m_children.GetCount(),
636 _T("Detach index is out of range") );
638 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
640 wxCHECK_MSG( node, false, _T("Failed to find child node") );
642 wxSizerItem *item = node->GetData();
644 if ( item->IsSizer() )
646 else if ( item->IsWindow() )
647 item->GetWindow()->SetContainingSizer( NULL );
650 m_children.Erase( node );
654 bool wxSizer::Replace( wxWindow *oldwin, wxWindow *newwin, bool recursive )
656 wxASSERT_MSG( oldwin, _T("Replacing NULL window") );
657 wxASSERT_MSG( newwin, _T("Replacing with NULL window") );
659 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
662 wxSizerItem *item = node->GetData();
664 if (item->GetWindow() == oldwin)
666 item->GetWindow()->SetContainingSizer( NULL );
667 item->SetWindow(newwin);
668 newwin->SetContainingSizer( this );
671 else if (recursive && item->IsSizer())
673 if (item->GetSizer()->Replace( oldwin, newwin, true ))
677 node = node->GetNext();
683 bool wxSizer::Replace( wxSizer *oldsz, wxSizer *newsz, bool recursive )
685 wxASSERT_MSG( oldsz, _T("Replacing NULL sizer") );
686 wxASSERT_MSG( newsz, _T("Replacing with NULL sizer") );
688 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
691 wxSizerItem *item = node->GetData();
693 if (item->GetSizer() == oldsz)
695 wxSizer *old = item->GetSizer();
696 item->SetSizer(newsz);
700 else if (recursive && item->IsSizer())
702 if (item->GetSizer()->Replace( oldsz, newsz, true ))
706 node = node->GetNext();
712 bool wxSizer::Replace( size_t old, wxSizerItem *newitem )
714 wxCHECK_MSG( old < m_children.GetCount(), false, _T("Replace index is out of range") );
715 wxASSERT_MSG( newitem, _T("Replacing with NULL item") );
717 wxSizerItemList::compatibility_iterator node = m_children.Item( old );
719 wxCHECK_MSG( node, false, _T("Failed to find child node") );
721 wxSizerItem *item = node->GetData();
722 node->SetData(newitem);
728 void wxSizer::Clear( bool delete_windows )
730 // First clear the ContainingSizer pointers
731 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
734 wxSizerItem *item = node->GetData();
736 if (item->IsWindow())
737 item->GetWindow()->SetContainingSizer( NULL );
738 node = node->GetNext();
741 // Destroy the windows if needed
745 // Now empty the list
746 WX_CLEAR_LIST(wxSizerItemList, m_children);
749 void wxSizer::DeleteWindows()
751 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
754 wxSizerItem *item = node->GetData();
756 item->DeleteWindows();
757 node = node->GetNext();
761 wxSize wxSizer::Fit( wxWindow *window )
763 wxSize size(window->IsTopLevel() ? FitSize(window)
764 : GetMinWindowSize(window));
766 window->SetSize( size );
771 void wxSizer::FitInside( wxWindow *window )
774 if (window->IsTopLevel())
775 size = VirtualFitSize( window );
777 size = GetMinClientSize( window );
779 window->SetVirtualSize( size );
782 void wxSizer::Layout()
784 // (re)calculates minimums needed for each item and other preparations
788 // Applies the layout and repositions/resizes the items
792 void wxSizer::SetSizeHints( wxWindow *window )
794 // Preserve the window's max size hints, but set the
795 // lower bound according to the sizer calculations.
797 wxSize size = Fit( window );
799 window->SetSizeHints( size.x,
801 window->GetMaxWidth(),
802 window->GetMaxHeight() );
805 void wxSizer::SetVirtualSizeHints( wxWindow *window )
807 // Preserve the window's max size hints, but set the
808 // lower bound according to the sizer calculations.
811 wxSize size( window->GetVirtualSize() );
812 window->SetVirtualSizeHints( size.x,
814 window->GetMaxWidth(),
815 window->GetMaxHeight() );
818 wxSize wxSizer::GetMaxWindowSize( wxWindow *window ) const
820 return window->GetMaxSize();
823 wxSize wxSizer::GetMinWindowSize( wxWindow *window )
825 wxSize minSize( GetMinSize() );
826 wxSize size( window->GetSize() );
827 wxSize client_size( window->GetClientSize() );
829 return wxSize( minSize.x+size.x-client_size.x,
830 minSize.y+size.y-client_size.y );
833 // TODO on mac we need a function that determines how much free space this
834 // min size contains, in order to make sure that we have 20 pixels of free
835 // space around the controls
837 // Return a window size that will fit within the screens dimensions
838 wxSize wxSizer::FitSize( wxWindow *window )
840 if ( window->IsTopLevel() )
842 wxTopLevelWindow *tlw = wxDynamicCast(window, wxTopLevelWindow);
843 if ( tlw && tlw->IsAlwaysMaximized() )
845 return tlw->GetClientSize();
849 wxSize size = GetMinWindowSize( window );
850 wxSize sizeMax = GetMaxWindowSize( window );
852 // Limit the size if sizeMax != wxDefaultSize
854 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
856 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
862 wxSize wxSizer::GetMaxClientSize( wxWindow *window ) const
864 wxSize maxSize( window->GetMaxSize() );
866 if ( maxSize != wxDefaultSize )
868 wxSize size( window->GetSize() );
869 wxSize client_size( window->GetClientSize() );
871 return wxSize( maxSize.x + client_size.x - size.x,
872 maxSize.y + client_size.y - size.y );
875 return wxDefaultSize;
878 wxSize wxSizer::GetMinClientSize( wxWindow *WXUNUSED(window) )
880 return GetMinSize(); // Already returns client size.
883 wxSize wxSizer::VirtualFitSize( wxWindow *window )
885 wxSize size = GetMinClientSize( window );
886 wxSize sizeMax = GetMaxClientSize( window );
888 // Limit the size if sizeMax != wxDefaultSize
890 if ( size.x > sizeMax.x && sizeMax.x != wxDefaultCoord )
892 if ( size.y > sizeMax.y && sizeMax.y != wxDefaultCoord )
898 void wxSizer::SetDimension( int x, int y, int width, int height )
907 wxSize wxSizer::GetMinSize()
909 wxSize ret( CalcMin() );
910 if (ret.x < m_minSize.x) ret.x = m_minSize.x;
911 if (ret.y < m_minSize.y) ret.y = m_minSize.y;
915 void wxSizer::DoSetMinSize( int width, int height )
918 m_minSize.y = height;
921 bool wxSizer::DoSetItemMinSize( wxWindow *window, int width, int height )
923 wxASSERT_MSG( window, _T("SetMinSize for NULL window") );
925 // Is it our immediate child?
927 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
930 wxSizerItem *item = node->GetData();
932 if (item->GetWindow() == window)
934 item->SetMinSize( width, height );
937 node = node->GetNext();
940 // No? Search any subsizers we own then
942 node = m_children.GetFirst();
945 wxSizerItem *item = node->GetData();
947 if ( item->GetSizer() &&
948 item->GetSizer()->DoSetItemMinSize( window, width, height ) )
950 // A child sizer found the requested windw, exit.
953 node = node->GetNext();
959 bool wxSizer::DoSetItemMinSize( wxSizer *sizer, int width, int height )
961 wxASSERT_MSG( sizer, _T("SetMinSize for NULL sizer") );
963 // Is it our immediate child?
965 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
968 wxSizerItem *item = node->GetData();
970 if (item->GetSizer() == sizer)
972 item->GetSizer()->DoSetMinSize( width, height );
975 node = node->GetNext();
978 // No? Search any subsizers we own then
980 node = m_children.GetFirst();
983 wxSizerItem *item = node->GetData();
985 if ( item->GetSizer() &&
986 item->GetSizer()->DoSetItemMinSize( sizer, width, height ) )
988 // A child found the requested sizer, exit.
991 node = node->GetNext();
997 bool wxSizer::DoSetItemMinSize( size_t index, int width, int height )
999 wxSizerItemList::compatibility_iterator node = m_children.Item( index );
1001 wxCHECK_MSG( node, false, _T("Failed to find child node") );
1003 wxSizerItem *item = node->GetData();
1005 if (item->GetSizer())
1007 // Sizers contains the minimal size in them, if not calculated ...
1008 item->GetSizer()->DoSetMinSize( width, height );
1012 // ... but the minimal size of spacers and windows is stored via the item
1013 item->SetMinSize( width, height );
1019 wxSizerItem* wxSizer::GetItem( wxWindow *window, bool recursive )
1021 wxASSERT_MSG( window, _T("GetItem for NULL window") );
1023 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1026 wxSizerItem *item = node->GetData();
1028 if (item->GetWindow() == window)
1032 else if (recursive && item->IsSizer())
1034 wxSizerItem *subitem = item->GetSizer()->GetItem( window, true );
1039 node = node->GetNext();
1045 wxSizerItem* wxSizer::GetItem( wxSizer *sizer, bool recursive )
1047 wxASSERT_MSG( sizer, _T("GetItem for NULL sizer") );
1049 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1052 wxSizerItem *item = node->GetData();
1054 if (item->GetSizer() == sizer)
1058 else if (recursive && item->IsSizer())
1060 wxSizerItem *subitem = item->GetSizer()->GetItem( sizer, true );
1065 node = node->GetNext();
1071 wxSizerItem* wxSizer::GetItem( size_t index )
1073 wxCHECK_MSG( index < m_children.GetCount(),
1075 _T("GetItem index is out of range") );
1077 return m_children.Item( index )->GetData();
1080 bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
1082 wxSizerItem *item = GetItem( window, recursive );
1093 bool wxSizer::Show( wxSizer *sizer, bool show, bool recursive )
1095 wxSizerItem *item = GetItem( sizer, recursive );
1106 bool wxSizer::Show( size_t index, bool show)
1108 wxSizerItem *item = GetItem( index );
1119 void wxSizer::ShowItems( bool show )
1121 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1124 node->GetData()->Show( show );
1125 node = node->GetNext();
1129 bool wxSizer::IsShown( wxWindow *window ) const
1131 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1134 wxSizerItem *item = node->GetData();
1136 if (item->GetWindow() == window)
1138 return item->IsShown();
1140 node = node->GetNext();
1143 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
1148 bool wxSizer::IsShown( wxSizer *sizer ) const
1150 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1153 wxSizerItem *item = node->GetData();
1155 if (item->GetSizer() == sizer)
1157 return item->IsShown();
1159 node = node->GetNext();
1162 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
1167 bool wxSizer::IsShown( size_t index ) const
1169 wxCHECK_MSG( index < m_children.GetCount(),
1171 _T("IsShown index is out of range") );
1173 return m_children.Item( index )->GetData()->IsShown();
1177 //---------------------------------------------------------------------------
1179 //---------------------------------------------------------------------------
1181 wxGridSizer::wxGridSizer( int rows, int cols, int vgap, int hgap )
1182 : m_rows( ( cols == 0 && rows == 0 ) ? 1 : rows )
1189 wxGridSizer::wxGridSizer( int cols, int vgap, int hgap )
1190 : m_rows( cols == 0 ? 1 : 0 )
1197 int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
1199 int nitems = m_children.GetCount();
1205 nrows = (nitems + m_cols - 1) / m_cols;
1209 ncols = (nitems + m_rows - 1) / m_rows;
1212 else // 0 columns, 0 rows?
1214 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
1223 void wxGridSizer::RecalcSizes()
1225 int nitems, nrows, ncols;
1226 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1229 wxSize sz( GetSize() );
1230 wxPoint pt( GetPosition() );
1232 int w = (sz.x - (ncols - 1) * m_hgap) / ncols;
1233 int h = (sz.y - (nrows - 1) * m_vgap) / nrows;
1236 for (int c = 0; c < ncols; c++)
1239 for (int r = 0; r < nrows; r++)
1241 int i = r * ncols + c;
1244 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1246 wxASSERT_MSG( node, _T("Failed to find SizerItemList node") );
1248 SetItemBounds( node->GetData(), x, y, w, h);
1256 wxSize wxGridSizer::CalcMin()
1259 if ( CalcRowsCols(nrows, ncols) == 0 )
1262 // Find the max width and height for any component
1266 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1269 wxSizerItem *item = node->GetData();
1270 wxSize sz( item->CalcMin() );
1272 w = wxMax( w, sz.x );
1273 h = wxMax( h, sz.y );
1275 node = node->GetNext();
1278 return wxSize( ncols * w + (ncols-1) * m_hgap,
1279 nrows * h + (nrows-1) * m_vgap );
1282 void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h )
1285 wxSize sz( item->GetMinSizeWithBorder() );
1286 int flag = item->GetFlag();
1288 if ((flag & wxEXPAND) || (flag & wxSHAPED))
1294 if (flag & wxALIGN_CENTER_HORIZONTAL)
1296 pt.x = x + (w - sz.x) / 2;
1298 else if (flag & wxALIGN_RIGHT)
1300 pt.x = x + (w - sz.x);
1303 if (flag & wxALIGN_CENTER_VERTICAL)
1305 pt.y = y + (h - sz.y) / 2;
1307 else if (flag & wxALIGN_BOTTOM)
1309 pt.y = y + (h - sz.y);
1313 item->SetDimension(pt, sz);
1316 //---------------------------------------------------------------------------
1318 //---------------------------------------------------------------------------
1320 wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap )
1321 : wxGridSizer( rows, cols, vgap, hgap ),
1322 m_flexDirection(wxBOTH),
1323 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1327 wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap )
1328 : wxGridSizer( cols, vgap, hgap ),
1329 m_flexDirection(wxBOTH),
1330 m_growMode(wxFLEX_GROWMODE_SPECIFIED)
1334 wxFlexGridSizer::~wxFlexGridSizer()
1338 void wxFlexGridSizer::RecalcSizes()
1340 int nitems, nrows, ncols;
1341 if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 )
1344 wxPoint pt( GetPosition() );
1345 wxSize sz( GetSize() );
1347 AdjustForGrowables(sz, m_calculatedMinSize, nrows, ncols);
1349 sz = wxSize( pt.x + sz.x, pt.y + sz.y );
1352 for (int c = 0; c < ncols; c++)
1355 for (int r = 0; r < nrows; r++)
1357 int i = r * ncols + c;
1360 wxSizerItemList::compatibility_iterator node = m_children.Item( i );
1362 wxASSERT_MSG( node, _T("Failed to find node") );
1364 int w = wxMax( 0, wxMin( m_colWidths[c], sz.x - x ) );
1365 int h = wxMax( 0, wxMin( m_rowHeights[r], sz.y - y ) );
1367 SetItemBounds( node->GetData(), x, y, w, h);
1369 if (m_rowHeights[r] != -1)
1370 y = y + m_rowHeights[r] + m_vgap;
1372 if (m_colWidths[c] != -1)
1373 x = x + m_colWidths[c] + m_hgap;
1377 wxSize wxFlexGridSizer::CalcMin()
1383 // Number of rows/columns can change as items are added or removed.
1384 if ( !CalcRowsCols(nrows, ncols) )
1387 m_rowHeights.SetCount(nrows);
1388 m_colWidths.SetCount(ncols);
1390 // We have to recalcuate the sizes in case the item minimum size has
1391 // changed since the previous layout, or the item has been hidden using
1392 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1393 // dimension of the row/column will be -1, indicating that the column
1394 // itself is hidden.
1395 for( s = m_rowHeights.GetCount(), i = 0; i < s; ++i )
1396 m_rowHeights[ i ] = -1;
1397 for( s = m_colWidths.GetCount(), i = 0; i < s; ++i )
1398 m_colWidths[ i ] = -1;
1400 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1405 wxSizerItem *item = node->GetData();
1406 if ( item->IsShown() )
1408 wxSize sz( item->CalcMin() );
1409 int row = i / ncols;
1410 int col = i % ncols;
1412 m_rowHeights[ row ] = wxMax( wxMax( 0, sz.y ), m_rowHeights[ row ] );
1413 m_colWidths[ col ] = wxMax( wxMax( 0, sz.x ), m_colWidths[ col ] );
1416 node = node->GetNext();
1420 AdjustForFlexDirection();
1422 // Sum total minimum size, including gaps between rows/columns.
1423 // -1 is used as a magic number meaning empty column.
1425 for (int col = 0; col < ncols; col++)
1426 if ( m_colWidths[ col ] != -1 )
1427 width += m_colWidths[ col ] + m_hgap;
1432 for (int row = 0; row < nrows; row++)
1433 if ( m_rowHeights[ row ] != -1 )
1434 height += m_rowHeights[ row ] + m_vgap;
1438 m_calculatedMinSize = wxSize( width, height );
1439 return m_calculatedMinSize;
1442 void wxFlexGridSizer::AdjustForFlexDirection()
1444 // the logic in CalcMin works when we resize flexibly in both directions
1445 // but maybe this is not the case
1446 if ( m_flexDirection != wxBOTH )
1448 // select the array corresponding to the direction in which we do *not*
1450 wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
1453 const size_t count = array.GetCount();
1455 // find the largest value in this array
1459 for ( n = 0; n < count; ++n )
1461 if ( array[n] > largest )
1465 // and now fill it with the largest value
1466 for ( n = 0; n < count; ++n )
1474 void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz, const wxSize& minsz,
1475 int nrows, int ncols)
1477 // what to do with the rows? by default, resize them proportionally
1478 if ( sz.y > minsz.y && ( (m_flexDirection & wxVERTICAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1480 int sum_proportions = 0;
1481 int growable_space = 0;
1484 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1486 // Since the number of rows/columns can change as items are
1487 // inserted/deleted, we need to verify at runtime that the
1488 // requested growable rows/columns are still valid.
1489 if (m_growableRows[idx] >= nrows)
1492 // If all items in a row/column are hidden, that row/column will
1493 // have a dimension of -1. This causes the row/column to be
1494 // hidden completely.
1495 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1497 sum_proportions += m_growableRowsProportions[idx];
1498 growable_space += m_rowHeights[ m_growableRows[idx] ];
1504 for (idx = 0; idx < m_growableRows.GetCount(); idx++)
1506 if (m_growableRows[idx] >= nrows )
1508 if (m_rowHeights[ m_growableRows[idx] ] == -1)
1509 m_rowHeights[ m_growableRows[idx] ] = 0;
1512 int delta = (sz.y - minsz.y);
1513 if (sum_proportions == 0)
1514 delta = (delta/num) + m_rowHeights[ m_growableRows[idx] ];
1516 delta = ((delta+growable_space)*m_growableRowsProportions[idx]) / sum_proportions;
1517 m_rowHeights[ m_growableRows[idx] ] = delta;
1522 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) )
1524 // rounding problem?
1525 for ( int row = 0; row < nrows; ++row )
1526 m_rowHeights[ row ] = sz.y / nrows;
1529 // the same logic as above but for the columns
1530 if ( sz.x > minsz.x && ( (m_flexDirection & wxHORIZONTAL) || (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) )
1532 int sum_proportions = 0;
1533 int growable_space = 0;
1536 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1538 // Since the number of rows/columns can change as items are
1539 // inserted/deleted, we need to verify at runtime that the
1540 // requested growable rows/columns are still valid.
1541 if (m_growableCols[idx] >= ncols)
1544 // If all items in a row/column are hidden, that row/column will
1545 // have a dimension of -1. This causes the column to be hidden
1547 if (m_colWidths[ m_growableCols[idx] ] == -1)
1549 sum_proportions += m_growableColsProportions[idx];
1550 growable_space += m_colWidths[ m_growableCols[idx] ];
1556 for (idx = 0; idx < m_growableCols.GetCount(); idx++)
1558 if (m_growableCols[idx] >= ncols )
1560 if (m_colWidths[ m_growableCols[idx] ] == -1)
1561 m_colWidths[ m_growableCols[idx] ] = 0;
1564 int delta = (sz.x - minsz.x);
1565 if (sum_proportions == 0)
1566 delta = (delta/num) + m_colWidths[ m_growableCols[idx] ];
1568 delta = ((delta+growable_space)*m_growableColsProportions[idx])/sum_proportions;
1569 m_colWidths[ m_growableCols[idx] ] = delta;
1574 else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) )
1576 for ( int col=0; col < ncols; ++col )
1577 m_colWidths[ col ] = sz.x / ncols;
1582 void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
1584 m_growableRows.Add( idx );
1585 m_growableRowsProportions.Add( proportion );
1588 void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
1590 m_growableCols.Add( idx );
1591 m_growableColsProportions.Add( proportion );
1594 // helper function for RemoveGrowableCol/Row()
1596 DoRemoveFromArrays(size_t idx, wxArrayInt& items, wxArrayInt& proportions)
1598 const size_t count = items.size();
1599 for ( size_t n = 0; n < count; n++ )
1601 if ( (size_t)items[n] == idx )
1604 proportions.RemoveAt(n);
1609 wxFAIL_MSG( _T("column/row is already not growable") );
1612 void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
1614 DoRemoveFromArrays(idx, m_growableCols, m_growableColsProportions);
1617 void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
1619 DoRemoveFromArrays(idx, m_growableRows, m_growableRowsProportions);
1622 //---------------------------------------------------------------------------
1624 //---------------------------------------------------------------------------
1626 wxBoxSizer::wxBoxSizer( int orient )
1627 : m_orient( orient )
1631 void wxBoxSizer::RecalcSizes()
1633 if (m_children.GetCount() == 0)
1639 if (m_orient == wxHORIZONTAL)
1640 delta = m_size.x - m_fixedWidth;
1642 delta = m_size.y - m_fixedHeight;
1645 wxPoint pt( m_position );
1647 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1650 wxSizerItem *item = node->GetData();
1652 if (item->IsShown())
1654 wxSize size( item->GetMinSizeWithBorder() );
1656 if (m_orient == wxVERTICAL)
1658 wxCoord height = size.y;
1659 if (item->GetProportion())
1661 // Because of at least one visible item has non-zero
1662 // proportion then m_stretchable is not zero
1663 height = (delta * item->GetProportion()) / m_stretchable;
1666 wxPoint child_pos( pt );
1667 wxSize child_size( size.x, height );
1669 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1670 child_size.x = m_size.x;
1671 else if (item->GetFlag() & wxALIGN_RIGHT)
1672 child_pos.x += m_size.x - size.x;
1673 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_HORIZONTAL))
1674 // XXX wxCENTER is added for backward compatibility;
1675 // wxALIGN_CENTER should be used in new code
1676 child_pos.x += (m_size.x - size.x) / 2;
1678 item->SetDimension( child_pos, child_size );
1684 wxCoord width = size.x;
1685 if (item->GetProportion())
1687 // Because of at least one visible item has non-zero
1688 // proportion then m_stretchable is not zero
1689 width = (delta * item->GetProportion()) / m_stretchable;
1692 wxPoint child_pos( pt );
1693 wxSize child_size( width, size.y );
1695 if (item->GetFlag() & (wxEXPAND | wxSHAPED))
1696 child_size.y = m_size.y;
1697 else if (item->GetFlag() & wxALIGN_BOTTOM)
1698 child_pos.y += m_size.y - size.y;
1699 else if (item->GetFlag() & (wxCENTER | wxALIGN_CENTER_VERTICAL))
1700 // XXX wxCENTER is added for backward compatibility;
1701 // wxALIGN_CENTER should be used in new code
1702 child_pos.y += (m_size.y - size.y) / 2;
1704 if ( m_containingWindow )
1706 child_pos.x = m_containingWindow->AdjustForLayoutDirection
1714 item->SetDimension( child_pos, child_size );
1720 node = node->GetNext();
1724 wxSize wxBoxSizer::CalcMin()
1726 if (m_children.GetCount() == 0)
1735 // precalc item minsizes and count proportions
1736 wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
1739 wxSizerItem *item = node->GetData();
1741 if ( item->IsShown() )
1743 item->CalcMin(); // result is stored in the item
1745 m_stretchable += item->GetProportion();
1748 node = node->GetNext();
1751 // Total minimum size (width or height) of sizer
1754 node = m_children.GetFirst();
1757 wxSizerItem *item = node->GetData();
1759 if (item->IsShown() && item->GetProportion() != 0)
1761 int stretch = item->GetProportion();
1762 wxSize size( item->GetMinSizeWithBorder() );
1765 // Integer division rounded up is (a + b - 1) / b
1766 // Round up needed in order to guarantee that all
1767 // all items will have size not less then their min size
1768 if (m_orient == wxHORIZONTAL)
1769 minSize = ( size.x*m_stretchable + stretch - 1)/stretch;
1771 minSize = ( size.y*m_stretchable + stretch - 1)/stretch;
1773 if (minSize > maxMinSize)
1774 maxMinSize = minSize;
1776 node = node->GetNext();
1779 // Calculate overall minimum size
1780 node = m_children.GetFirst();
1783 wxSizerItem *item = node->GetData();
1785 if (item->IsShown())
1787 wxSize size( item->GetMinSizeWithBorder() );
1788 if (item->GetProportion() != 0)
1790 if (m_orient == wxHORIZONTAL)
1791 size.x = (maxMinSize*item->GetProportion())/m_stretchable;
1793 size.y = (maxMinSize*item->GetProportion())/m_stretchable;
1797 if (m_orient == wxVERTICAL)
1799 m_fixedHeight += size.y;
1800 m_fixedWidth = wxMax( m_fixedWidth, size.x );
1804 m_fixedWidth += size.x;
1805 m_fixedHeight = wxMax( m_fixedHeight, size.y );
1809 if (m_orient == wxHORIZONTAL)
1811 m_minWidth += size.x;
1812 m_minHeight = wxMax( m_minHeight, size.y );
1816 m_minHeight += size.y;
1817 m_minWidth = wxMax( m_minWidth, size.x );
1820 node = node->GetNext();
1823 return wxSize( m_minWidth, m_minHeight );
1826 //---------------------------------------------------------------------------
1828 //---------------------------------------------------------------------------
1832 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
1833 : wxBoxSizer( orient ),
1836 wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
1838 // do this so that our Detach() is called if the static box is destroyed
1840 m_staticBox->SetContainingSizer(this);
1843 wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
1844 : wxBoxSizer(orient),
1845 m_staticBox(new wxStaticBox(win, wxID_ANY, s))
1848 m_staticBox->SetContainingSizer(this);
1851 wxStaticBoxSizer::~wxStaticBoxSizer()
1856 static void GetStaticBoxBorders( wxStaticBox *box,
1860 // this has to be done platform by platform as there is no way to
1861 // guess the thickness of a wxStaticBox border
1862 box->GetBordersForSizer(borderTop, borderOther);
1865 void wxStaticBoxSizer::RecalcSizes()
1867 int top_border, other_border;
1868 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1870 m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
1872 wxPoint old_pos( m_position );
1873 m_position.x += other_border;
1874 m_position.y += top_border;
1875 wxSize old_size( m_size );
1876 m_size.x -= 2*other_border;
1877 m_size.y -= top_border + other_border;
1879 wxBoxSizer::RecalcSizes();
1881 m_position = old_pos;
1885 wxSize wxStaticBoxSizer::CalcMin()
1887 int top_border, other_border;
1888 GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
1890 wxSize ret( wxBoxSizer::CalcMin() );
1891 ret.x += 2*other_border;
1892 ret.y += other_border + top_border;
1897 void wxStaticBoxSizer::ShowItems( bool show )
1899 m_staticBox->Show( show );
1900 wxBoxSizer::ShowItems( show );
1903 bool wxStaticBoxSizer::Detach( wxWindow *window )
1905 // avoid deleting m_staticBox in our dtor if it's being detached from the
1906 // sizer (which can happen because it's being already destroyed for
1908 if ( window == m_staticBox )
1914 return wxSizer::Detach( window );
1917 #endif // wxUSE_STATBOX
1921 wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1922 : wxBoxSizer(wxHORIZONTAL)
1924 // Vertical buttons with lots of space on either side
1925 // looks rubbish on WinCE, so let's not do this for now.
1926 // If we are going to use vertical buttons, we should
1927 // put the sizer to the right of other controls in the dialog,
1928 // and that's beyond the scope of this sizer.
1930 bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
1931 // If we have a PDA screen, put yes/no button over
1932 // all other buttons, otherwise on the left side.
1934 m_orient = wxVERTICAL;
1937 m_buttonAffirmative = NULL;
1938 m_buttonApply = NULL;
1939 m_buttonNegative = NULL;
1940 m_buttonCancel = NULL;
1941 m_buttonHelp = NULL;
1944 void wxStdDialogButtonSizer::AddButton(wxButton *mybutton)
1946 switch (mybutton->GetId())
1951 m_buttonAffirmative = mybutton;
1954 m_buttonApply = mybutton;
1957 m_buttonNegative = mybutton;
1960 m_buttonCancel = mybutton;
1963 case wxID_CONTEXT_HELP:
1964 m_buttonHelp = mybutton;
1971 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton *button )
1973 m_buttonAffirmative = button;
1976 void wxStdDialogButtonSizer::SetNegativeButton( wxButton *button )
1978 m_buttonNegative = button;
1981 void wxStdDialogButtonSizer::SetCancelButton( wxButton *button )
1983 m_buttonCancel = button;
1986 void wxStdDialogButtonSizer::Realize()
1989 Add(0, 0, 0, wxLEFT, 6);
1991 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
1993 if (m_buttonNegative){
1994 // HIG POLICE BULLETIN - destructive buttons need extra padding
1995 // 24 pixels on either side
1996 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 12);
1999 // extra whitespace between help/negative and cancel/ok buttons
2000 Add(0, 0, 1, wxEXPAND, 0);
2002 if (m_buttonCancel){
2003 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
2004 // Cancel or help should be default
2005 // m_buttonCancel->SetDefaultButton();
2008 // Ugh, Mac doesn't really have apply dialogs, so I'll just
2009 // figure the best place is between Cancel and OK
2011 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 6);
2013 if (m_buttonAffirmative){
2014 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
2016 if (m_buttonAffirmative->GetId() == wxID_SAVE){
2017 // these buttons have set labels under Mac so we should use them
2018 m_buttonAffirmative->SetLabel(_("Save"));
2019 m_buttonNegative->SetLabel(_("Don't Save"));
2023 // Extra space around and at the right
2025 #elif defined(__WXGTK20__)
2026 Add(0, 0, 0, wxLEFT, 9);
2028 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
2030 // extra whitespace between help and cancel/ok buttons
2031 Add(0, 0, 1, wxEXPAND, 0);
2033 if (m_buttonNegative){
2034 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
2037 if (m_buttonCancel){
2038 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
2039 // Cancel or help should be default
2040 // m_buttonCancel->SetDefaultButton();
2044 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, 3);
2046 if (m_buttonAffirmative)
2047 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT, 6);
2048 #elif defined(__WXMSW__)
2051 // right-justify buttons
2052 Add(0, 0, 1, wxEXPAND, 0);
2054 if (m_buttonAffirmative){
2055 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(2, 0)).x);
2058 if (m_buttonNegative){
2059 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(2, 0)).x);
2062 if (m_buttonCancel){
2063 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(2, 0)).x);
2066 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(2, 0)).x);
2069 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(2, 0)).x);
2071 // GTK+1 and any other platform
2073 // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
2075 Add((wxWindow*)m_buttonHelp, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonHelp->ConvertDialogToPixels(wxSize(4, 0)).x);
2077 // extra whitespace between help and cancel/ok buttons
2078 Add(0, 0, 1, wxEXPAND, 0);
2081 Add((wxWindow*)m_buttonApply, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonApply->ConvertDialogToPixels(wxSize(4, 0)).x);
2083 if (m_buttonAffirmative){
2084 Add((wxWindow*)m_buttonAffirmative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonAffirmative->ConvertDialogToPixels(wxSize(4, 0)).x);
2087 if (m_buttonNegative){
2088 Add((wxWindow*)m_buttonNegative, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonNegative->ConvertDialogToPixels(wxSize(4, 0)).x);
2091 if (m_buttonCancel){
2092 Add((wxWindow*)m_buttonCancel, 0, wxALIGN_CENTRE | wxLEFT | wxRIGHT, m_buttonCancel->ConvertDialogToPixels(wxSize(4, 0)).x);
2093 // Cancel or help should be default
2094 // m_buttonCancel->SetDefaultButton();
2100 #endif // wxUSE_BUTTON
2102 #if WXWIN_COMPATIBILITY_2_4
2104 // ----------------------------------------------------------------------------
2106 // ----------------------------------------------------------------------------
2109 IMPLEMENT_CLASS(wxBookCtrlSizer, wxSizer)
2111 IMPLEMENT_CLASS(wxNotebookSizer, wxBookCtrlSizer)
2112 #endif // wxUSE_NOTEBOOK
2113 #endif // wxUSE_BOOKCTRL
2117 #if WXWIN_COMPATIBILITY_2_6
2119 wxBookCtrlSizer::wxBookCtrlSizer(wxBookCtrlBase *bookctrl)
2120 : m_bookctrl(bookctrl)
2122 wxASSERT_MSG( bookctrl, wxT("wxBookCtrlSizer needs a control") );
2125 #endif // WXWIN_COMPATIBILITY_2_6
2127 void wxBookCtrlSizer::RecalcSizes()
2129 m_bookctrl->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
2132 wxSize wxBookCtrlSizer::CalcMin()
2134 wxSize sizeBorder = m_bookctrl->CalcSizeFromPage(wxSize(0,0));
2139 if ( m_bookctrl->GetPageCount() == 0 )
2141 return wxSize(sizeBorder.x + 10, sizeBorder.y + 10);
2147 wxWindowList::compatibility_iterator
2148 node = m_bookctrl->GetChildren().GetFirst();
2151 wxWindow *item = node->GetData();
2152 wxSizer *itemsizer = item->GetSizer();
2156 wxSize subsize( itemsizer->CalcMin() );
2158 if (subsize.x > maxX)
2160 if (subsize.y > maxY)
2164 node = node->GetNext();
2167 return wxSize( maxX, maxY ) + sizeBorder;
2172 #if WXWIN_COMPATIBILITY_2_6
2174 wxNotebookSizer::wxNotebookSizer(wxNotebook *nb)
2176 wxASSERT_MSG( nb, wxT("wxNotebookSizer needs a control") );
2180 #endif // WXWIN_COMPATIBILITY_2_6
2182 #endif // wxUSE_NOTEBOOOK
2183 #endif // wxUSE_BOOKCTRL
2185 #endif // WXWIN_COMPATIBILITY_2_4