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"
20 #include "wx/display.h"
24 #include "wx/string.h"
28 #include "wx/settings.h"
29 #include "wx/button.h"
30 #include "wx/statbox.h"
31 #include "wx/toplevel.h"
34 #if wxUSE_SYSTEM_OPTIONS
35 #include "wx/sysopt.h"
38 #include "wx/listimpl.cpp"
41 //---------------------------------------------------------------------------
43 IMPLEMENT_CLASS(wxSizerItem
, wxObject
)
44 IMPLEMENT_CLASS(wxSizer
, wxObject
)
45 IMPLEMENT_CLASS(wxGridSizer
, wxSizer
)
46 IMPLEMENT_CLASS(wxFlexGridSizer
, wxGridSizer
)
47 IMPLEMENT_CLASS(wxBoxSizer
, wxSizer
)
49 IMPLEMENT_CLASS(wxStaticBoxSizer
, wxBoxSizer
)
52 IMPLEMENT_CLASS(wxStdDialogButtonSizer
, wxBoxSizer
)
55 WX_DEFINE_EXPORTED_LIST( wxSizerItemList
)
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 void wxSizerItem::Init(const wxSizerFlags
& flags
)
98 m_proportion
= flags
.GetProportion();
99 m_flag
= flags
.GetFlags();
100 m_border
= flags
.GetBorderInPixels();
103 wxSizerItem::wxSizerItem()
114 void wxSizerItem::DoSetWindow(wxWindow
*window
)
116 wxCHECK_RET( window
, _T("NULL window in wxSizerItem::SetWindow()") );
118 m_kind
= Item_Window
;
121 // window doesn't become smaller than its initial size, whatever happens
122 m_minSize
= window
->GetSize();
124 if ( m_flag
& wxFIXED_MINSIZE
)
125 window
->SetMinSize(m_minSize
);
127 // aspect ratio calculated from initial size
131 wxSizerItem::wxSizerItem(wxWindow
*window
,
137 m_proportion(proportion
),
147 void wxSizerItem::DoSetSizer(wxSizer
*sizer
)
153 wxSizerItem::wxSizerItem(wxSizer
*sizer
,
160 m_proportion(proportion
),
169 // m_minSize is set later
173 void wxSizerItem::DoSetSpacer(const wxSize
& size
)
175 m_kind
= Item_Spacer
;
176 m_spacer
= new wxSizerSpacer(size
);
181 wxSizerItem::wxSizerItem(int width
,
189 m_minSize(width
, height
), // minimal size is the initial size
190 m_proportion(proportion
),
196 DoSetSpacer(wxSize(width
, height
));
199 wxSizerItem::~wxSizerItem()
205 void wxSizerItem::Free()
213 m_window
->SetContainingSizer(NULL
);
226 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
232 wxSize
wxSizerItem::GetSpacer() const
235 if ( m_kind
== Item_Spacer
)
236 size
= m_spacer
->GetSize();
242 wxSize
wxSizerItem::GetSize() const
251 ret
= m_window
->GetSize();
255 ret
= m_sizer
->GetSize();
259 ret
= m_spacer
->GetSize();
264 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
271 if (m_flag
& wxNORTH
)
273 if (m_flag
& wxSOUTH
)
279 wxSize
wxSizerItem::CalcMin()
283 m_minSize
= m_sizer
->GetMinSize();
285 // if we have to preserve aspect ratio _AND_ this is
286 // the first-time calculation, consider ret to be initial size
287 if ( (m_flag
& wxSHAPED
) && wxIsNullDouble(m_ratio
) )
290 else if ( IsWindow() )
292 // Since the size of the window may change during runtime, we
293 // should use the current minimal/best size.
294 m_minSize
= m_window
->GetEffectiveMinSize();
297 return GetMinSizeWithBorder();
300 wxSize
wxSizerItem::GetMinSizeWithBorder() const
302 wxSize ret
= m_minSize
;
308 if (m_flag
& wxNORTH
)
310 if (m_flag
& wxSOUTH
)
317 void wxSizerItem::SetDimension( const wxPoint
& pos_
, const wxSize
& size_
)
321 if (m_flag
& wxSHAPED
)
323 // adjust aspect ratio
324 int rwidth
= (int) (size
.y
* m_ratio
);
328 int rheight
= (int) (size
.x
/ m_ratio
);
329 // add vertical space
330 if (m_flag
& wxALIGN_CENTER_VERTICAL
)
331 pos
.y
+= (size
.y
- rheight
) / 2;
332 else if (m_flag
& wxALIGN_BOTTOM
)
333 pos
.y
+= (size
.y
- rheight
);
334 // use reduced dimensions
337 else if (rwidth
< size
.x
)
339 // add horizontal space
340 if (m_flag
& wxALIGN_CENTER_HORIZONTAL
)
341 pos
.x
+= (size
.x
- rwidth
) / 2;
342 else if (m_flag
& wxALIGN_RIGHT
)
343 pos
.x
+= (size
.x
- rwidth
);
348 // This is what GetPosition() returns. Since we calculate
349 // borders afterwards, GetPosition() will be the left/top
350 // corner of the surrounding border.
362 if (m_flag
& wxNORTH
)
367 if (m_flag
& wxSOUTH
)
377 m_rect
= wxRect(pos
, size
);
382 wxFAIL_MSG( _T("can't set size of uninitialized sizer item") );
386 m_window
->SetSize(pos
.x
, pos
.y
, size
.x
, size
.y
,
387 wxSIZE_ALLOW_MINUS_ONE
);
391 m_sizer
->SetDimension(pos
.x
, pos
.y
, size
.x
, size
.y
);
395 m_spacer
->SetSize(size
);
400 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
404 void wxSizerItem::DeleteWindows()
413 //We are deleting the window from this sizer - normally
414 //the window destroys the sizer associated with it,
415 //which might destroy this, which we don't want
416 m_window
->SetContainingSizer(NULL
);
418 //Putting this after the switch will result in a spacer
419 //not being deleted properly on destruction
424 m_sizer
->DeleteWindows();
429 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
434 void wxSizerItem::Show( bool show
)
439 wxFAIL_MSG( _T("can't show uninitialized sizer item") );
443 m_window
->Show(show
);
451 m_spacer
->Show(show
);
456 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
460 bool wxSizerItem::IsShown() const
465 // we may be called from CalcMin(), just return false so that we're
470 return m_window
->IsShown();
473 // arbitrarily decide that if at least one of our elements is
474 // shown, so are we (this arbitrariness is the reason for
475 // deprecating this function)
477 // Some apps (such as dialog editors) depend on an empty sizer still
478 // being laid out correctly and reporting the correct size and position.
479 if (m_sizer
->GetChildren().GetCount() == 0)
482 for ( wxSizerItemList::compatibility_iterator
483 node
= m_sizer
->GetChildren().GetFirst();
485 node
= node
->GetNext() )
487 if ( node
->GetData()->IsShown() )
494 return m_spacer
->IsShown();
498 wxFAIL_MSG( _T("unexpected wxSizerItem::m_kind") );
504 #if WXWIN_COMPATIBILITY_2_6
505 void wxSizerItem::SetOption( int option
)
507 SetProportion( option
);
510 int wxSizerItem::GetOption() const
512 return GetProportion();
514 #endif // WXWIN_COMPATIBILITY_2_6
517 //---------------------------------------------------------------------------
519 //---------------------------------------------------------------------------
523 WX_CLEAR_LIST(wxSizerItemList
, m_children
);
526 wxSizerItem
* wxSizer::Insert( size_t index
, wxSizerItem
*item
)
528 m_children
.Insert( index
, item
);
530 if ( item
->GetWindow() )
531 item
->GetWindow()->SetContainingSizer( this );
533 if ( item
->GetSizer() )
534 item
->GetSizer()->SetContainingWindow( m_containingWindow
);
539 void wxSizer::SetContainingWindow(wxWindow
*win
)
541 if ( win
== m_containingWindow
)
544 m_containingWindow
= win
;
546 // set the same window for all nested sizers as well, they also are in the
548 for ( wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
550 node
= node
->GetNext() )
552 wxSizerItem
*const item
= node
->GetData();
553 wxSizer
*const sizer
= item
->GetSizer();
557 sizer
->SetContainingWindow(win
);
562 #if WXWIN_COMPATIBILITY_2_6
563 bool wxSizer::Remove( wxWindow
*window
)
565 return Detach( window
);
567 #endif // WXWIN_COMPATIBILITY_2_6
569 bool wxSizer::Remove( wxSizer
*sizer
)
571 wxASSERT_MSG( sizer
, _T("Removing NULL sizer") );
573 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
576 wxSizerItem
*item
= node
->GetData();
578 if (item
->GetSizer() == sizer
)
581 m_children
.Erase( node
);
585 node
= node
->GetNext();
591 bool wxSizer::Remove( int index
)
593 wxCHECK_MSG( index
>= 0 && (size_t)index
< m_children
.GetCount(),
595 _T("Remove index is out of range") );
597 wxSizerItemList::compatibility_iterator node
= m_children
.Item( index
);
599 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
601 delete node
->GetData();
602 m_children
.Erase( node
);
607 bool wxSizer::Detach( wxSizer
*sizer
)
609 wxASSERT_MSG( sizer
, _T("Detaching NULL sizer") );
611 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
614 wxSizerItem
*item
= node
->GetData();
616 if (item
->GetSizer() == sizer
)
620 m_children
.Erase( node
);
623 node
= node
->GetNext();
629 bool wxSizer::Detach( wxWindow
*window
)
631 wxASSERT_MSG( window
, _T("Detaching NULL window") );
633 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
636 wxSizerItem
*item
= node
->GetData();
638 if (item
->GetWindow() == window
)
641 m_children
.Erase( node
);
644 node
= node
->GetNext();
650 bool wxSizer::Detach( int index
)
652 wxCHECK_MSG( index
>= 0 && (size_t)index
< m_children
.GetCount(),
654 _T("Detach index is out of range") );
656 wxSizerItemList::compatibility_iterator node
= m_children
.Item( index
);
658 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
660 wxSizerItem
*item
= node
->GetData();
662 if ( item
->IsSizer() )
666 m_children
.Erase( node
);
670 bool wxSizer::Replace( wxWindow
*oldwin
, wxWindow
*newwin
, bool recursive
)
672 wxASSERT_MSG( oldwin
, _T("Replacing NULL window") );
673 wxASSERT_MSG( newwin
, _T("Replacing with NULL window") );
675 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
678 wxSizerItem
*item
= node
->GetData();
680 if (item
->GetWindow() == oldwin
)
682 item
->AssignWindow(newwin
);
683 newwin
->SetContainingSizer( this );
686 else if (recursive
&& item
->IsSizer())
688 if (item
->GetSizer()->Replace( oldwin
, newwin
, true ))
692 node
= node
->GetNext();
698 bool wxSizer::Replace( wxSizer
*oldsz
, wxSizer
*newsz
, bool recursive
)
700 wxASSERT_MSG( oldsz
, _T("Replacing NULL sizer") );
701 wxASSERT_MSG( newsz
, _T("Replacing with NULL sizer") );
703 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
706 wxSizerItem
*item
= node
->GetData();
708 if (item
->GetSizer() == oldsz
)
710 item
->AssignSizer(newsz
);
713 else if (recursive
&& item
->IsSizer())
715 if (item
->GetSizer()->Replace( oldsz
, newsz
, true ))
719 node
= node
->GetNext();
725 bool wxSizer::Replace( size_t old
, wxSizerItem
*newitem
)
727 wxCHECK_MSG( old
< m_children
.GetCount(), false, _T("Replace index is out of range") );
728 wxASSERT_MSG( newitem
, _T("Replacing with NULL item") );
730 wxSizerItemList::compatibility_iterator node
= m_children
.Item( old
);
732 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
734 wxSizerItem
*item
= node
->GetData();
735 node
->SetData(newitem
);
741 void wxSizer::Clear( bool delete_windows
)
743 // First clear the ContainingSizer pointers
744 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
747 wxSizerItem
*item
= node
->GetData();
749 if (item
->IsWindow())
750 item
->GetWindow()->SetContainingSizer( NULL
);
751 node
= node
->GetNext();
754 // Destroy the windows if needed
758 // Now empty the list
759 WX_CLEAR_LIST(wxSizerItemList
, m_children
);
762 void wxSizer::DeleteWindows()
764 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
767 wxSizerItem
*item
= node
->GetData();
769 item
->DeleteWindows();
770 node
= node
->GetNext();
774 wxSize
wxSizer::Fit( wxWindow
*window
)
776 // take the min size by default and limit it by max size
777 wxSize size
= GetMinWindowSize(window
);
778 wxSize sizeMax
= GetMaxWindowSize(window
);
780 wxTopLevelWindow
*tlw
= wxDynamicCast(window
, wxTopLevelWindow
);
783 // hack for small screen devices where TLWs are always full screen
784 if ( tlw
->IsAlwaysMaximized() )
786 size
= tlw
->GetSize();
788 else // normal situation
790 // limit the window to the size of the display it is on
791 int disp
= wxDisplay::GetFromWindow(window
);
792 if ( disp
== wxNOT_FOUND
)
794 // or, if we don't know which one it is, of the main one
798 sizeMax
= wxDisplay(disp
).GetClientArea().GetSize();
800 #if wxUSE_SYSTEM_OPTIONS
801 int marginX
= wxSystemOptions::GetOptionInt(wxT("sizer.desktopmargin.x"));
802 int marginY
= wxSystemOptions::GetOptionInt(wxT("sizer.desktopmargin.y"));
803 sizeMax
.x
-= marginX
;
804 sizeMax
.y
-= marginY
;
809 if ( sizeMax
.x
!= wxDefaultCoord
&& size
.x
> sizeMax
.x
)
811 if ( sizeMax
.y
!= wxDefaultCoord
&& size
.y
> sizeMax
.y
)
815 window
->SetSize( size
);
820 void wxSizer::FitInside( wxWindow
*window
)
823 if (window
->IsTopLevel())
824 size
= VirtualFitSize( window
);
826 size
= GetMinClientSize( window
);
828 window
->SetVirtualSize( size
);
831 void wxSizer::Layout()
833 // (re)calculates minimums needed for each item and other preparations
837 // Applies the layout and repositions/resizes the items
841 void wxSizer::SetSizeHints( wxWindow
*window
)
843 // Preserve the window's max size hints, but set the
844 // lower bound according to the sizer calculations.
846 wxSize size
= Fit( window
);
848 window
->SetSizeHints( size
.x
,
850 window
->GetMaxWidth(),
851 window
->GetMaxHeight() );
854 void wxSizer::SetVirtualSizeHints( wxWindow
*window
)
856 // Preserve the window's max size hints, but set the
857 // lower bound according to the sizer calculations.
860 wxSize
size( window
->GetVirtualSize() );
861 window
->SetVirtualSizeHints( size
.x
,
863 window
->GetMaxWidth(),
864 window
->GetMaxHeight() );
867 wxSize
wxSizer::GetMaxWindowSize( wxWindow
*window
) const
869 return window
->GetMaxSize();
872 wxSize
wxSizer::GetMinWindowSize( wxWindow
*window
)
874 wxSize
minSize( GetMinSize() );
875 wxSize
size( window
->GetSize() );
876 wxSize
client_size( window
->GetClientSize() );
878 return wxSize( minSize
.x
+size
.x
-client_size
.x
,
879 minSize
.y
+size
.y
-client_size
.y
);
882 // TODO on mac we need a function that determines how much free space this
883 // min size contains, in order to make sure that we have 20 pixels of free
884 // space around the controls
885 wxSize
wxSizer::GetMaxClientSize( wxWindow
*window
) const
887 wxSize
maxSize( window
->GetMaxSize() );
889 if ( maxSize
!= wxDefaultSize
)
891 wxSize
size( window
->GetSize() );
892 wxSize
client_size( window
->GetClientSize() );
894 return wxSize( maxSize
.x
+ client_size
.x
- size
.x
,
895 maxSize
.y
+ client_size
.y
- size
.y
);
898 return wxDefaultSize
;
901 wxSize
wxSizer::GetMinClientSize( wxWindow
*WXUNUSED(window
) )
903 return GetMinSize(); // Already returns client size.
906 wxSize
wxSizer::VirtualFitSize( wxWindow
*window
)
908 wxSize size
= GetMinClientSize( window
);
909 wxSize sizeMax
= GetMaxClientSize( window
);
911 // Limit the size if sizeMax != wxDefaultSize
913 if ( size
.x
> sizeMax
.x
&& sizeMax
.x
!= wxDefaultCoord
)
915 if ( size
.y
> sizeMax
.y
&& sizeMax
.y
!= wxDefaultCoord
)
921 void wxSizer::SetDimension( int x
, int y
, int width
, int height
)
930 wxSize
wxSizer::GetMinSize()
932 wxSize
ret( CalcMin() );
933 if (ret
.x
< m_minSize
.x
) ret
.x
= m_minSize
.x
;
934 if (ret
.y
< m_minSize
.y
) ret
.y
= m_minSize
.y
;
938 void wxSizer::DoSetMinSize( int width
, int height
)
941 m_minSize
.y
= height
;
944 bool wxSizer::DoSetItemMinSize( wxWindow
*window
, int width
, int height
)
946 wxASSERT_MSG( window
, _T("SetMinSize for NULL window") );
948 // Is it our immediate child?
950 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
953 wxSizerItem
*item
= node
->GetData();
955 if (item
->GetWindow() == window
)
957 item
->SetMinSize( width
, height
);
960 node
= node
->GetNext();
963 // No? Search any subsizers we own then
965 node
= m_children
.GetFirst();
968 wxSizerItem
*item
= node
->GetData();
970 if ( item
->GetSizer() &&
971 item
->GetSizer()->DoSetItemMinSize( window
, width
, height
) )
973 // A child sizer found the requested windw, exit.
976 node
= node
->GetNext();
982 bool wxSizer::DoSetItemMinSize( wxSizer
*sizer
, int width
, int height
)
984 wxASSERT_MSG( sizer
, _T("SetMinSize for NULL sizer") );
986 // Is it our immediate child?
988 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
991 wxSizerItem
*item
= node
->GetData();
993 if (item
->GetSizer() == sizer
)
995 item
->GetSizer()->DoSetMinSize( width
, height
);
998 node
= node
->GetNext();
1001 // No? Search any subsizers we own then
1003 node
= m_children
.GetFirst();
1006 wxSizerItem
*item
= node
->GetData();
1008 if ( item
->GetSizer() &&
1009 item
->GetSizer()->DoSetItemMinSize( sizer
, width
, height
) )
1011 // A child found the requested sizer, exit.
1014 node
= node
->GetNext();
1020 bool wxSizer::DoSetItemMinSize( size_t index
, int width
, int height
)
1022 wxSizerItemList::compatibility_iterator node
= m_children
.Item( index
);
1024 wxCHECK_MSG( node
, false, _T("Failed to find child node") );
1026 wxSizerItem
*item
= node
->GetData();
1028 if (item
->GetSizer())
1030 // Sizers contains the minimal size in them, if not calculated ...
1031 item
->GetSizer()->DoSetMinSize( width
, height
);
1035 // ... but the minimal size of spacers and windows is stored via the item
1036 item
->SetMinSize( width
, height
);
1042 wxSizerItem
* wxSizer::GetItem( wxWindow
*window
, bool recursive
)
1044 wxASSERT_MSG( window
, _T("GetItem for NULL window") );
1046 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1049 wxSizerItem
*item
= node
->GetData();
1051 if (item
->GetWindow() == window
)
1055 else if (recursive
&& item
->IsSizer())
1057 wxSizerItem
*subitem
= item
->GetSizer()->GetItem( window
, true );
1062 node
= node
->GetNext();
1068 wxSizerItem
* wxSizer::GetItem( wxSizer
*sizer
, bool recursive
)
1070 wxASSERT_MSG( sizer
, _T("GetItem for NULL sizer") );
1072 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1075 wxSizerItem
*item
= node
->GetData();
1077 if (item
->GetSizer() == sizer
)
1081 else if (recursive
&& item
->IsSizer())
1083 wxSizerItem
*subitem
= item
->GetSizer()->GetItem( sizer
, true );
1088 node
= node
->GetNext();
1094 wxSizerItem
* wxSizer::GetItem( size_t index
)
1096 wxCHECK_MSG( index
< m_children
.GetCount(),
1098 _T("GetItem index is out of range") );
1100 return m_children
.Item( index
)->GetData();
1103 wxSizerItem
* wxSizer::GetItemById( int id
, bool recursive
)
1105 // This gets a sizer item by the id of the sizer item
1106 // and NOT the id of a window if the item is a window.
1108 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1111 wxSizerItem
*item
= node
->GetData();
1113 if (item
->GetId() == id
)
1117 else if (recursive
&& item
->IsSizer())
1119 wxSizerItem
*subitem
= item
->GetSizer()->GetItemById( id
, true );
1124 node
= node
->GetNext();
1130 bool wxSizer::Show( wxWindow
*window
, bool show
, bool recursive
)
1132 wxSizerItem
*item
= GetItem( window
, recursive
);
1143 bool wxSizer::Show( wxSizer
*sizer
, bool show
, bool recursive
)
1145 wxSizerItem
*item
= GetItem( sizer
, recursive
);
1156 bool wxSizer::Show( size_t index
, bool show
)
1158 wxSizerItem
*item
= GetItem( index
);
1169 void wxSizer::ShowItems( bool show
)
1171 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1174 node
->GetData()->Show( show
);
1175 node
= node
->GetNext();
1179 bool wxSizer::IsShown( wxWindow
*window
) const
1181 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1184 wxSizerItem
*item
= node
->GetData();
1186 if (item
->GetWindow() == window
)
1188 return item
->IsShown();
1190 node
= node
->GetNext();
1193 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
1198 bool wxSizer::IsShown( wxSizer
*sizer
) const
1200 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1203 wxSizerItem
*item
= node
->GetData();
1205 if (item
->GetSizer() == sizer
)
1207 return item
->IsShown();
1209 node
= node
->GetNext();
1212 wxFAIL_MSG( _T("IsShown failed to find sizer item") );
1217 bool wxSizer::IsShown( size_t index
) const
1219 wxCHECK_MSG( index
< m_children
.GetCount(),
1221 _T("IsShown index is out of range") );
1223 return m_children
.Item( index
)->GetData()->IsShown();
1227 //---------------------------------------------------------------------------
1229 //---------------------------------------------------------------------------
1231 wxGridSizer::wxGridSizer( int rows
, int cols
, int vgap
, int hgap
)
1232 : m_rows( ( cols
== 0 && rows
== 0 ) ? 1 : rows
)
1239 wxGridSizer::wxGridSizer( int cols
, int vgap
, int hgap
)
1240 : m_rows( cols
== 0 ? 1 : 0 )
1247 int wxGridSizer::CalcRowsCols(int& nrows
, int& ncols
) const
1249 int nitems
= m_children
.GetCount();
1255 nrows
= (nitems
+ m_cols
- 1) / m_cols
;
1259 ncols
= (nitems
+ m_rows
- 1) / m_rows
;
1262 else // 0 columns, 0 rows?
1264 wxFAIL_MSG( _T("grid sizer must have either rows or columns fixed") );
1273 void wxGridSizer::RecalcSizes()
1275 int nitems
, nrows
, ncols
;
1276 if ( (nitems
= CalcRowsCols(nrows
, ncols
)) == 0 )
1279 wxSize
sz( GetSize() );
1280 wxPoint
pt( GetPosition() );
1282 int w
= (sz
.x
- (ncols
- 1) * m_hgap
) / ncols
;
1283 int h
= (sz
.y
- (nrows
- 1) * m_vgap
) / nrows
;
1286 for (int c
= 0; c
< ncols
; c
++)
1289 for (int r
= 0; r
< nrows
; r
++)
1291 int i
= r
* ncols
+ c
;
1294 wxSizerItemList::compatibility_iterator node
= m_children
.Item( i
);
1296 wxASSERT_MSG( node
, _T("Failed to find SizerItemList node") );
1298 SetItemBounds( node
->GetData(), x
, y
, w
, h
);
1306 wxSize
wxGridSizer::CalcMin()
1309 if ( CalcRowsCols(nrows
, ncols
) == 0 )
1312 // Find the max width and height for any component
1316 wxSizerItemList::compatibility_iterator node
= m_children
.GetFirst();
1319 wxSizerItem
*item
= node
->GetData();
1320 wxSize
sz( item
->CalcMin() );
1322 w
= wxMax( w
, sz
.x
);
1323 h
= wxMax( h
, sz
.y
);
1325 node
= node
->GetNext();
1328 return wxSize( ncols
* w
+ (ncols
-1) * m_hgap
,
1329 nrows
* h
+ (nrows
-1) * m_vgap
);
1332 void wxGridSizer::SetItemBounds( wxSizerItem
*item
, int x
, int y
, int w
, int h
)
1335 wxSize
sz( item
->GetMinSizeWithBorder() );
1336 int flag
= item
->GetFlag();
1338 if ((flag
& wxEXPAND
) || (flag
& wxSHAPED
))
1344 if (flag
& wxALIGN_CENTER_HORIZONTAL
)
1346 pt
.x
= x
+ (w
- sz
.x
) / 2;
1348 else if (flag
& wxALIGN_RIGHT
)
1350 pt
.x
= x
+ (w
- sz
.x
);
1353 if (flag
& wxALIGN_CENTER_VERTICAL
)
1355 pt
.y
= y
+ (h
- sz
.y
) / 2;
1357 else if (flag
& wxALIGN_BOTTOM
)
1359 pt
.y
= y
+ (h
- sz
.y
);
1363 item
->SetDimension(pt
, sz
);
1366 //---------------------------------------------------------------------------
1368 //---------------------------------------------------------------------------
1370 wxFlexGridSizer::wxFlexGridSizer( int rows
, int cols
, int vgap
, int hgap
)
1371 : wxGridSizer( rows
, cols
, vgap
, hgap
),
1372 m_flexDirection(wxBOTH
),
1373 m_growMode(wxFLEX_GROWMODE_SPECIFIED
)
1377 wxFlexGridSizer::wxFlexGridSizer( int cols
, int vgap
, int hgap
)
1378 : wxGridSizer( cols
, vgap
, hgap
),
1379 m_flexDirection(wxBOTH
),
1380 m_growMode(wxFLEX_GROWMODE_SPECIFIED
)
1384 wxFlexGridSizer::~wxFlexGridSizer()
1388 void wxFlexGridSizer::RecalcSizes()
1391 if ( !CalcRowsCols(nrows
, ncols
) )
1394 const wxPoint
pt(GetPosition());
1395 const wxSize
sz(GetSize());
1397 AdjustForGrowables(sz
);
1399 wxSizerItemList::const_iterator i
= m_children
.begin();
1400 const wxSizerItemList::const_iterator end
= m_children
.end();
1403 for ( int r
= 0; r
< nrows
; r
++ )
1405 if ( m_rowHeights
[r
] == -1 )
1407 // this row is entirely hidden, skip it
1408 for ( int c
= 0; c
< ncols
; c
++ )
1419 const int hrow
= m_rowHeights
[r
];
1420 int h
= sz
.y
- y
; // max remaining height, don't overflow it
1425 for ( int c
= 0; c
< ncols
&& i
!= end
; c
++, ++i
)
1427 const int wcol
= m_colWidths
[c
];
1432 int w
= sz
.x
- x
; // max possible value, ensure we don't overflow
1436 SetItemBounds(*i
, pt
.x
+ x
, pt
.y
+ y
, w
, h
);
1448 // helper function used in CalcMin() to sum up the sizes of non-hidden items
1449 static int SumArraySizes(const wxArrayInt
& sizes
, int gap
)
1451 // Sum total minimum size, including gaps between rows/columns.
1452 // -1 is used as a magic number meaning empty row/column.
1455 const size_t count
= sizes
.size();
1456 for ( size_t n
= 0; n
< count
; n
++ )
1458 if ( sizes
[n
] != -1 )
1461 total
+= gap
; // separate from the previous column
1470 wxSize
wxFlexGridSizer::CalcMin()
1475 // Number of rows/columns can change as items are added or removed.
1476 if ( !CalcRowsCols(nrows
, ncols
) )
1480 // We have to recalculate the sizes in case the item minimum size has
1481 // changed since the previous layout, or the item has been hidden using
1482 // wxSizer::Show(). If all the items in a row/column are hidden, the final
1483 // dimension of the row/column will be -1, indicating that the column
1484 // itself is hidden.
1485 m_rowHeights
.assign(nrows
, -1);
1486 m_colWidths
.assign(ncols
, -1);
1488 // n is the index of the item in left-to-right top-to-bottom order
1490 for ( wxSizerItemList::iterator i
= m_children
.begin();
1491 i
!= m_children
.end();
1494 wxSizerItem
* const item
= *i
;
1495 if ( item
->IsShown() )
1497 const wxSize
sz(item
->CalcMin());
1499 const int row
= n
/ ncols
;
1500 const int col
= n
% ncols
;
1502 if ( sz
.y
> m_rowHeights
[row
] )
1503 m_rowHeights
[row
] = sz
.y
;
1504 if ( sz
.x
> m_colWidths
[col
] )
1505 m_colWidths
[col
] = sz
.x
;
1509 AdjustForFlexDirection();
1511 m_calculatedMinSize
= wxSize(SumArraySizes(m_colWidths
, m_hgap
),
1512 SumArraySizes(m_rowHeights
, m_vgap
));
1514 return m_calculatedMinSize
;
1517 void wxFlexGridSizer::AdjustForFlexDirection()
1519 // the logic in CalcMin works when we resize flexibly in both directions
1520 // but maybe this is not the case
1521 if ( m_flexDirection
!= wxBOTH
)
1523 // select the array corresponding to the direction in which we do *not*
1525 wxArrayInt
& array
= m_flexDirection
== wxVERTICAL
? m_colWidths
1528 const size_t count
= array
.GetCount();
1530 // find the largest value in this array
1534 for ( n
= 0; n
< count
; ++n
)
1536 if ( array
[n
] > largest
)
1540 // and now fill it with the largest value
1541 for ( n
= 0; n
< count
; ++n
)
1543 // don't touch hidden rows
1544 if ( array
[n
] != -1 )
1550 // helper of AdjustForGrowables() which is called for rows/columns separately
1553 // delta: the extra space, we do nothing unless it's positive
1554 // growable: indices or growable rows/cols in sizes array
1555 // sizes: the height/widths of rows/cols to adjust
1556 // proportions: proportions of the growable rows/cols or NULL if they all
1557 // should be assumed to have proportion of 1
1559 DoAdjustForGrowables(int delta
,
1560 const wxArrayInt
& growable
,
1562 const wxArrayInt
*proportions
)
1567 // total sum of proportions of all non-hidden rows
1568 int sum_proportions
= 0;
1570 // number of currently shown growable rows
1573 const int max_idx
= sizes
.size();
1575 const size_t count
= growable
.size();
1577 for ( idx
= 0; idx
< count
; idx
++ )
1579 // Since the number of rows/columns can change as items are
1580 // inserted/deleted, we need to verify at runtime that the
1581 // requested growable rows/columns are still valid.
1582 if ( growable
[idx
] >= max_idx
)
1585 // If all items in a row/column are hidden, that row/column will
1586 // have a dimension of -1. This causes the row/column to be
1587 // hidden completely.
1588 if ( sizes
[growable
[idx
]] == -1 )
1592 sum_proportions
+= (*proportions
)[idx
];
1600 // the remaining extra free space, adjusted during each iteration
1601 for ( idx
= 0; idx
< count
; idx
++ )
1603 if ( growable
[idx
] >= max_idx
)
1606 if ( sizes
[ growable
[idx
] ] == -1 )
1610 if ( sum_proportions
== 0 )
1612 // no growable rows -- divide extra space evenly among all
1613 cur_delta
= delta
/num
;
1616 else // allocate extra space proportionally
1618 const int cur_prop
= (*proportions
)[idx
];
1619 cur_delta
= (delta
*cur_prop
)/sum_proportions
;
1620 sum_proportions
-= cur_prop
;
1623 sizes
[growable
[idx
]] += cur_delta
;
1628 void wxFlexGridSizer::AdjustForGrowables(const wxSize
& sz
)
1630 if ( (m_flexDirection
& wxVERTICAL
) || (m_growMode
!= wxFLEX_GROWMODE_NONE
) )
1632 // pass NULL instead of proportions if the grow mode is ALL as we
1633 // should treat all rows as having proportion of 1 then
1634 DoAdjustForGrowables
1636 sz
.y
- m_calculatedMinSize
.y
,
1639 m_growMode
== wxFLEX_GROWMODE_SPECIFIED
? &m_growableRowsProportions
1644 if ( (m_flexDirection
& wxHORIZONTAL
) || (m_growMode
!= wxFLEX_GROWMODE_NONE
) )
1646 DoAdjustForGrowables
1648 sz
.x
- m_calculatedMinSize
.x
,
1651 m_growMode
== wxFLEX_GROWMODE_SPECIFIED
? &m_growableColsProportions
1658 void wxFlexGridSizer::AddGrowableRow( size_t idx
, int proportion
)
1660 m_growableRows
.Add( idx
);
1661 m_growableRowsProportions
.Add( proportion
);
1664 void wxFlexGridSizer::AddGrowableCol( size_t idx
, int proportion
)
1666 m_growableCols
.Add( idx
);
1667 m_growableColsProportions
.Add( proportion
);
1670 // helper function for RemoveGrowableCol/Row()
1672 DoRemoveFromArrays(size_t idx
, wxArrayInt
& items
, wxArrayInt
& proportions
)
1674 const size_t count
= items
.size();
1675 for ( size_t n
= 0; n
< count
; n
++ )
1677 if ( (size_t)items
[n
] == idx
)
1680 proportions
.RemoveAt(n
);
1685 wxFAIL_MSG( _T("column/row is already not growable") );
1688 void wxFlexGridSizer::RemoveGrowableCol( size_t idx
)
1690 DoRemoveFromArrays(idx
, m_growableCols
, m_growableColsProportions
);
1693 void wxFlexGridSizer::RemoveGrowableRow( size_t idx
)
1695 DoRemoveFromArrays(idx
, m_growableRows
, m_growableRowsProportions
);
1698 //---------------------------------------------------------------------------
1700 //---------------------------------------------------------------------------
1702 void wxBoxSizer::RecalcSizes()
1704 if ( m_children
.empty() )
1707 // the amount of free space which we should redistribute among the
1708 // stretchable items (i.e. those with non zero proportion)
1709 int delta
= SizeInMajorDir(m_size
) - SizeInMajorDir(m_minSize
);
1711 // the position at which we put the next child
1712 wxPoint
pt(m_position
);
1714 const wxCoord totalMinorSize
= SizeInMinorDir(m_size
);
1716 int totalProportion
= m_totalProportion
;
1717 for ( wxSizerItemList::const_iterator i
= m_children
.begin();
1718 i
!= m_children
.end();
1721 wxSizerItem
* const item
= *i
;
1723 if ( !item
->IsShown() )
1726 // DMC doesn't distinguish between
1727 // int SizeInMajorDir(const wxSize& sz) const
1728 // and int& SizeInMajorDir(wxSize& sz)
1731 wxSize
sizeThis(item
->GetMinSizeWithBorder());
1734 // adjust the size in the major direction using the proportion
1735 wxCoord majorSize
= SizeInMajorDir(sizeThis
);
1736 const int propItem
= item
->GetProportion();
1739 const int deltaItem
= (delta
* propItem
) / totalProportion
;
1741 majorSize
+= deltaItem
;
1744 totalProportion
-= propItem
;
1748 // apply the alignment in the minor direction
1749 wxPoint
posChild(pt
);
1751 wxCoord minorSize
= SizeInMinorDir(sizeThis
);
1752 const int flag
= item
->GetFlag();
1753 if ( flag
& (wxEXPAND
| wxSHAPED
) )
1755 minorSize
= totalMinorSize
;
1757 else if ( flag
& (IsVertical() ? wxALIGN_RIGHT
: wxALIGN_BOTTOM
) )
1759 PosInMinorDir(posChild
) += totalMinorSize
- minorSize
;
1761 // NB: wxCENTRE is used here only for backwards compatibility,
1762 // wxALIGN_CENTRE should be used in new code
1763 else if ( flag
& (wxCENTER
| wxALIGN_CENTRE
) )
1765 PosInMinorDir(posChild
) += (totalMinorSize
- minorSize
) / 2;
1769 // apply RTL adjustment for horizontal sizers:
1770 if ( !IsVertical() && m_containingWindow
)
1772 posChild
.x
= m_containingWindow
->AdjustForLayoutDirection
1780 // finally set size of this child and advance to the next one
1781 item
->SetDimension(posChild
, SizeFromMajorMinor(majorSize
, minorSize
));
1783 PosInMajorDir(pt
) += majorSize
;
1787 wxSize
wxBoxSizer::CalcMin()
1789 m_totalProportion
= 0;
1790 m_minSize
= wxSize(0, 0);
1792 // calculate the minimal sizes for all items and count sum of proportions
1793 for ( wxSizerItemList::const_iterator i
= m_children
.begin();
1794 i
!= m_children
.end();
1797 wxSizerItem
* const item
= *i
;
1799 if ( !item
->IsShown() )
1802 const // see __DMC__ above
1804 wxSize sizeMinThis
= item
->CalcMin();
1806 SizeInMajorDir(m_minSize
) += SizeInMajorDir(sizeMinThis
);
1807 if ( SizeInMinorDir(sizeMinThis
) > SizeInMinorDir(m_minSize
) )
1808 SizeInMinorDir(m_minSize
) = SizeInMinorDir(sizeMinThis
);
1810 m_totalProportion
+= item
->GetProportion();
1816 //---------------------------------------------------------------------------
1818 //---------------------------------------------------------------------------
1822 wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox
*box
, int orient
)
1823 : wxBoxSizer( orient
),
1826 wxASSERT_MSG( box
, wxT("wxStaticBoxSizer needs a static box") );
1828 // do this so that our Detach() is called if the static box is destroyed
1830 m_staticBox
->SetContainingSizer(this);
1833 wxStaticBoxSizer::wxStaticBoxSizer(int orient
, wxWindow
*win
, const wxString
& s
)
1834 : wxBoxSizer(orient
),
1835 m_staticBox(new wxStaticBox(win
, wxID_ANY
, s
))
1838 m_staticBox
->SetContainingSizer(this);
1841 wxStaticBoxSizer::~wxStaticBoxSizer()
1846 static void GetStaticBoxBorders( wxStaticBox
*box
,
1850 // this has to be done platform by platform as there is no way to
1851 // guess the thickness of a wxStaticBox border
1852 box
->GetBordersForSizer(borderTop
, borderOther
);
1855 void wxStaticBoxSizer::RecalcSizes()
1857 int top_border
, other_border
;
1858 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1860 m_staticBox
->SetSize( m_position
.x
, m_position
.y
, m_size
.x
, m_size
.y
);
1862 wxPoint
old_pos( m_position
);
1863 m_position
.x
+= other_border
;
1864 m_position
.y
+= top_border
;
1865 wxSize
old_size( m_size
);
1866 m_size
.x
-= 2*other_border
;
1867 m_size
.y
-= top_border
+ other_border
;
1869 wxBoxSizer::RecalcSizes();
1871 m_position
= old_pos
;
1875 wxSize
wxStaticBoxSizer::CalcMin()
1877 int top_border
, other_border
;
1878 GetStaticBoxBorders(m_staticBox
, &top_border
, &other_border
);
1880 wxSize
ret( wxBoxSizer::CalcMin() );
1881 ret
.x
+= 2*other_border
;
1882 ret
.y
+= other_border
+ top_border
;
1887 void wxStaticBoxSizer::ShowItems( bool show
)
1889 m_staticBox
->Show( show
);
1890 wxBoxSizer::ShowItems( show
);
1893 bool wxStaticBoxSizer::Detach( wxWindow
*window
)
1895 // avoid deleting m_staticBox in our dtor if it's being detached from the
1896 // sizer (which can happen because it's being already destroyed for
1898 if ( window
== m_staticBox
)
1904 return wxSizer::Detach( window
);
1907 #endif // wxUSE_STATBOX
1911 wxStdDialogButtonSizer::wxStdDialogButtonSizer()
1912 : wxBoxSizer(wxHORIZONTAL
)
1914 // Vertical buttons with lots of space on either side
1915 // looks rubbish on WinCE, so let's not do this for now.
1916 // If we are going to use vertical buttons, we should
1917 // put the sizer to the right of other controls in the dialog,
1918 // and that's beyond the scope of this sizer.
1920 bool is_pda
= (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
);
1921 // If we have a PDA screen, put yes/no button over
1922 // all other buttons, otherwise on the left side.
1924 m_orient
= wxVERTICAL
;
1927 m_buttonAffirmative
= NULL
;
1928 m_buttonApply
= NULL
;
1929 m_buttonNegative
= NULL
;
1930 m_buttonCancel
= NULL
;
1931 m_buttonHelp
= NULL
;
1934 void wxStdDialogButtonSizer::AddButton(wxButton
*mybutton
)
1936 switch (mybutton
->GetId())
1941 m_buttonAffirmative
= mybutton
;
1944 m_buttonApply
= mybutton
;
1947 m_buttonNegative
= mybutton
;
1951 m_buttonCancel
= mybutton
;
1954 case wxID_CONTEXT_HELP
:
1955 m_buttonHelp
= mybutton
;
1962 void wxStdDialogButtonSizer::SetAffirmativeButton( wxButton
*button
)
1964 m_buttonAffirmative
= button
;
1967 void wxStdDialogButtonSizer::SetNegativeButton( wxButton
*button
)
1969 m_buttonNegative
= button
;
1972 void wxStdDialogButtonSizer::SetCancelButton( wxButton
*button
)
1974 m_buttonCancel
= button
;
1977 void wxStdDialogButtonSizer::Realize()
1980 Add(0, 0, 0, wxLEFT
, 6);
1982 Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 6);
1984 if (m_buttonNegative
){
1985 // HIG POLICE BULLETIN - destructive buttons need extra padding
1986 // 24 pixels on either side
1987 Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 12);
1990 // extra whitespace between help/negative and cancel/ok buttons
1991 Add(0, 0, 1, wxEXPAND
, 0);
1993 if (m_buttonCancel
){
1994 Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 6);
1995 // Cancel or help should be default
1996 // m_buttonCancel->SetDefaultButton();
1999 // Ugh, Mac doesn't really have apply dialogs, so I'll just
2000 // figure the best place is between Cancel and OK
2002 Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 6);
2004 if (m_buttonAffirmative
){
2005 Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE
| wxLEFT
, 6);
2007 if (m_buttonAffirmative
->GetId() == wxID_SAVE
){
2008 // these buttons have set labels under Mac so we should use them
2009 m_buttonAffirmative
->SetLabel(_("Save"));
2010 if (m_buttonNegative
)
2011 m_buttonNegative
->SetLabel(_("Don't Save"));
2015 // Extra space around and at the right
2017 #elif defined(__WXGTK20__)
2018 Add(0, 0, 0, wxLEFT
, 9);
2020 Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 3);
2022 // extra whitespace between help and cancel/ok buttons
2023 Add(0, 0, 1, wxEXPAND
, 0);
2025 if (m_buttonNegative
){
2026 Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 3);
2029 // according to HIG, in explicit apply windows the order is:
2030 // [ Help Apply Cancel OK ]
2032 Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 3);
2034 if (m_buttonCancel
){
2035 Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, 3);
2036 // Cancel or help should be default
2037 // m_buttonCancel->SetDefaultButton();
2040 if (m_buttonAffirmative
)
2041 Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE
| wxLEFT
, 6);
2042 #elif defined(__WXMSW__)
2045 // right-justify buttons
2046 Add(0, 0, 1, wxEXPAND
, 0);
2048 if (m_buttonAffirmative
){
2049 Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(2, 0)).x
);
2052 if (m_buttonNegative
){
2053 Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(2, 0)).x
);
2056 if (m_buttonCancel
){
2057 Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(2, 0)).x
);
2060 Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(2, 0)).x
);
2063 Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(2, 0)).x
);
2065 // GTK+1 and any other platform
2067 // Add(0, 0, 0, wxLEFT, 5); // Not sure what this was for but it unbalances the dialog
2069 Add((wxWindow
*)m_buttonHelp
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonHelp
->ConvertDialogToPixels(wxSize(4, 0)).x
);
2071 // extra whitespace between help and cancel/ok buttons
2072 Add(0, 0, 1, wxEXPAND
, 0);
2075 Add((wxWindow
*)m_buttonApply
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonApply
->ConvertDialogToPixels(wxSize(4, 0)).x
);
2077 if (m_buttonAffirmative
){
2078 Add((wxWindow
*)m_buttonAffirmative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonAffirmative
->ConvertDialogToPixels(wxSize(4, 0)).x
);
2081 if (m_buttonNegative
){
2082 Add((wxWindow
*)m_buttonNegative
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonNegative
->ConvertDialogToPixels(wxSize(4, 0)).x
);
2085 if (m_buttonCancel
){
2086 Add((wxWindow
*)m_buttonCancel
, 0, wxALIGN_CENTRE
| wxLEFT
| wxRIGHT
, m_buttonCancel
->ConvertDialogToPixels(wxSize(4, 0)).x
);
2087 // Cancel or help should be default
2088 // m_buttonCancel->SetDefaultButton();
2094 #endif // wxUSE_BUTTON