1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Layout sample
4 // Author: Julian Smart
5 // Modified by: Robin Dunn, Vadim Zeitlin
8 // Copyright: (c) 1998 Julian Smart
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
13 // ----------------------------------------------------------------------------
15 // ----------------------------------------------------------------------------
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
29 #include "wx/gbsizer.h"
30 #include "wx/statline.h"
31 #include "wx/notebook.h"
32 #include "wx/spinctrl.h"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
44 // Create the main frame window
45 MyFrame
*frame
= new MyFrame
;
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
57 EVT_MENU(LAYOUT_ABOUT
, MyFrame::OnAbout
)
58 EVT_MENU(LAYOUT_QUIT
, MyFrame::OnQuit
)
60 EVT_MENU(LAYOUT_TEST_PROPORTIONS
, MyFrame::TestProportions
)
61 EVT_MENU(LAYOUT_TEST_SIZER
, MyFrame::TestFlexSizers
)
62 EVT_MENU(LAYOUT_TEST_NB_SIZER
, MyFrame::TestNotebookSizers
)
63 EVT_MENU(LAYOUT_TEST_GB_SIZER
, MyFrame::TestGridBagSizer
)
66 // Define my frame constructor
68 : wxFrame(NULL
, wxID_ANY
, _T("wxWidgets Layout Demo"),
69 wxDefaultPosition
, wxDefaultSize
,
70 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
73 wxMenu
*file_menu
= new wxMenu
;
75 file_menu
->Append(LAYOUT_TEST_PROPORTIONS
, _T("&Proportions demo...\tF1"));
76 file_menu
->Append(LAYOUT_TEST_SIZER
, _T("Test wx&FlexSizer...\tF2"));
77 file_menu
->Append(LAYOUT_TEST_NB_SIZER
, _T("Test ¬ebook sizers...\tF3"));
78 file_menu
->Append(LAYOUT_TEST_GB_SIZER
, _T("Test &gridbag sizer...\tF4"));
80 file_menu
->AppendSeparator();
81 file_menu
->Append(LAYOUT_QUIT
, _T("E&xit"), _T("Quit program"));
83 wxMenu
*help_menu
= new wxMenu
;
84 help_menu
->Append(LAYOUT_ABOUT
, _T("&About"), _T("About layout demo..."));
86 wxMenuBar
*menu_bar
= new wxMenuBar
;
88 menu_bar
->Append(file_menu
, _T("&File"));
89 menu_bar
->Append(help_menu
, _T("&Help"));
91 // Associate the menu bar with the frame
96 SetStatusText(_T("wxWidgets layout demo"));
97 #endif // wxUSE_STATUSBAR
99 wxPanel
* p
= new wxPanel(this, -1);
101 // we want to get a dialog that is stretchable because it
102 // has a text ctrl in the middle. at the bottom, we have
103 // two buttons which.
105 wxBoxSizer
*topsizer
= new wxBoxSizer( wxVERTICAL
);
107 // 1) top: create wxStaticText with minimum size equal to its default size
109 new wxStaticText( p
, wxID_ANY
, _T("An explanation (wxALIGN_RIGHT).") ),
110 wxSizerFlags().Align(wxALIGN_RIGHT
).Border(wxALL
& ~wxBOTTOM
, 5));
112 // 2) top: create wxTextCtrl with minimum size (100x60)
114 new wxTextCtrl( p
, wxID_ANY
, _T("My text (wxEXPAND)."), wxDefaultPosition
, wxSize(100,60), wxTE_MULTILINE
),
115 wxSizerFlags(1).Expand().Border(wxALL
, 5));
117 // 2.5) Gratuitous test of wxStaticBoxSizers
118 wxBoxSizer
*statsizer
= new wxStaticBoxSizer(
119 new wxStaticBox(p
, wxID_ANY
, _T("A wxStaticBoxSizer")), wxVERTICAL
);
121 new wxStaticText(p
, wxID_ANY
, _T("And some TEXT inside it")),
122 wxSizerFlags().Center().Border(wxALL
, 30));
125 wxSizerFlags(1).Expand().Border(wxALL
, 10));
127 // 2.7) And a test of wxGridSizer
128 wxGridSizer
*gridsizer
= new wxGridSizer(2, 5, 5);
129 gridsizer
->Add(new wxStaticText(p
, wxID_ANY
, _T("Label")),
130 wxSizerFlags().Align(wxALIGN_RIGHT
| wxALIGN_CENTER_VERTICAL
));
131 gridsizer
->Add(new wxTextCtrl(p
, wxID_ANY
, _T("Grid sizer demo")),
132 wxSizerFlags(1).Align(wxGROW
| wxALIGN_CENTER_VERTICAL
));
133 gridsizer
->Add(new wxStaticText(p
, wxID_ANY
, _T("Another label")),
134 wxSizerFlags().Align(wxALIGN_RIGHT
| wxALIGN_CENTER_VERTICAL
));
135 gridsizer
->Add(new wxTextCtrl(p
, wxID_ANY
, _T("More text")),
136 wxSizerFlags(1).Align(wxGROW
| wxALIGN_CENTER_VERTICAL
));
137 gridsizer
->Add(new wxStaticText(p
, wxID_ANY
, _T("Final label")),
138 wxSizerFlags().Align(wxALIGN_RIGHT
| wxALIGN_CENTER_VERTICAL
));
139 gridsizer
->Add(new wxTextCtrl(p
, wxID_ANY
, _T("And yet more text")),
140 wxSizerFlags().Align(wxGROW
| wxALIGN_CENTER_VERTICAL
));
143 wxSizerFlags().Proportion(1).Expand().Border(wxALL
, 10));
147 // 3) middle: create wxStaticLine with minimum size (3x3)
149 new wxStaticLine( p
, wxID_ANY
, wxDefaultPosition
, wxSize(3,3), wxHORIZONTAL
),
150 wxSizerFlags().Expand());
151 #endif // wxUSE_STATLINE
154 // 4) bottom: create two centred wxButtons
155 wxBoxSizer
*button_box
= new wxBoxSizer( wxHORIZONTAL
);
157 new wxButton( p
, wxID_ANY
, _T("Two buttons in a box") ),
158 wxSizerFlags().Border(wxALL
, 7));
160 new wxButton( p
, wxID_ANY
, _T("(wxCENTER)") ),
161 wxSizerFlags().Border(wxALL
, 7));
163 topsizer
->Add(button_box
, wxSizerFlags().Center());
165 p
->SetSizer( topsizer
);
167 // don't allow frame to get smaller than what the sizers tell it and also set
168 // the initial size as calculated by the sizers
169 topsizer
->SetSizeHints( this );
172 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
177 void MyFrame::TestProportions(wxCommandEvent
& WXUNUSED(event
))
179 (new MyProportionsFrame(this))->Show();
182 void MyFrame::TestFlexSizers(wxCommandEvent
& WXUNUSED(event
) )
184 MyFlexSizerFrame
*newFrame
= new MyFlexSizerFrame(_T("Flex Sizer Test Frame"), 50, 50);
185 newFrame
->Show(true);
188 void MyFrame::TestNotebookSizers(wxCommandEvent
& WXUNUSED(event
) )
190 MySizerDialog
dialog( this, _T("Notebook Sizer Test Dialog") );
196 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
) )
198 (void)wxMessageBox(_T("wxWidgets GUI library layout demo\n"),
199 _T("About Layout Demo"), wxOK
|wxICON_INFORMATION
);
202 void MyFrame::TestGridBagSizer(wxCommandEvent
& WXUNUSED(event
) )
204 MyGridBagSizerFrame
*newFrame
= new
205 MyGridBagSizerFrame(_T("wxGridBagSizer Test Frame"), 50, 50);
206 newFrame
->Show(true);
209 // ----------------------------------------------------------------------------
210 // MyProportionsFrame
211 // ----------------------------------------------------------------------------
213 MyProportionsFrame::MyProportionsFrame(wxFrame
*parent
)
214 : wxFrame(parent
, wxID_ANY
, _T("Box Sizer Proportions Demo"))
218 // create the controls
219 wxPanel
*panel
= new wxPanel(this, wxID_ANY
);
220 for ( n
= 0; n
< WXSIZEOF(m_spins
); n
++ )
222 m_spins
[n
] = new wxSpinCtrl(panel
);
223 m_spins
[n
]->SetValue(n
);
227 m_sizer
= new wxStaticBoxSizer(wxHORIZONTAL
, panel
,
228 _T("Try changing elements proportions and resizing the window"));
229 for ( n
= 0; n
< WXSIZEOF(m_spins
); n
++ )
230 m_sizer
->Add(m_spins
[n
], wxSizerFlags().Border());
232 // put everything together
233 panel
->SetSizer(m_sizer
);
234 wxSizer
*sizerTop
= new wxBoxSizer(wxVERTICAL
);
235 sizerTop
->Add(panel
, wxSizerFlags(1).Expand().Border());
237 SetSizerAndFit(sizerTop
);
239 // and connect the events
240 Connect(wxEVT_COMMAND_TEXT_UPDATED
,
241 wxCommandEventHandler(MyProportionsFrame::OnProportionUpdated
));
242 Connect(wxEVT_COMMAND_SPINCTRL_UPDATED
,
243 wxSpinEventHandler(MyProportionsFrame::OnProportionChanged
));
246 void MyProportionsFrame::UpdateProportions()
248 for ( size_t n
= 0; n
< WXSIZEOF(m_spins
); n
++ )
250 m_sizer
->GetItem(n
)->SetProportion(m_spins
[n
]->GetValue());
256 void MyProportionsFrame::OnProportionUpdated(wxCommandEvent
& WXUNUSED(event
))
261 void MyProportionsFrame::OnProportionChanged(wxSpinEvent
& WXUNUSED(event
))
266 // ----------------------------------------------------------------------------
268 // ----------------------------------------------------------------------------
270 void MyFlexSizerFrame::InitFlexSizer(wxFlexGridSizer
*sizer
, wxWindow
* parent
)
272 for ( int i
= 0; i
< 3; i
++ )
274 for ( int j
= 0; j
< 3; j
++ )
276 sizer
->Add(new wxStaticText
280 wxString::Format(_T("(%d, %d)"), i
+ 1, j
+ 1),
285 0, wxEXPAND
| wxALIGN_CENTER_VERTICAL
| wxALL
, 3);
290 MyFlexSizerFrame::MyFlexSizerFrame(const wxChar
*title
, int x
, int y
)
291 : wxFrame(NULL
, wxID_ANY
, title
, wxPoint(x
, y
) )
293 wxFlexGridSizer
*sizerFlex
;
294 wxPanel
* p
= new wxPanel(this, -1);
296 // consttuct the first column
297 wxSizer
*sizerCol1
= new wxBoxSizer(wxVERTICAL
);
298 sizerCol1
->Add(new wxStaticText(p
, wxID_ANY
, _T("Ungrowable:")), 0, wxCENTER
| wxTOP
, 20);
299 sizerFlex
= new wxFlexGridSizer(3, 3);
300 InitFlexSizer(sizerFlex
, p
);
301 sizerCol1
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
303 sizerCol1
->Add(new wxStaticText(p
, wxID_ANY
, _T("Growable middle column:")), 0, wxCENTER
| wxTOP
, 20);
304 sizerFlex
= new wxFlexGridSizer(3, 3);
305 InitFlexSizer(sizerFlex
, p
);
306 sizerFlex
->AddGrowableCol(1);
307 sizerCol1
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
309 sizerCol1
->Add(new wxStaticText(p
, wxID_ANY
, _T("Growable middle row:")), 0, wxCENTER
| wxTOP
, 20);
310 sizerFlex
= new wxFlexGridSizer(3, 3);
311 InitFlexSizer(sizerFlex
, p
);
312 sizerFlex
->AddGrowableRow(1);
313 sizerCol1
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
315 sizerCol1
->Add(new wxStaticText(p
, wxID_ANY
, _T("All growable columns:")), 0, wxCENTER
| wxTOP
, 20);
316 sizerFlex
= new wxFlexGridSizer(3, 3);
317 InitFlexSizer(sizerFlex
, p
);
318 sizerFlex
->AddGrowableCol(0, 1);
319 sizerFlex
->AddGrowableCol(1, 2);
320 sizerFlex
->AddGrowableCol(2, 3);
321 sizerCol1
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
324 wxSizer
*sizerCol2
= new wxBoxSizer(wxVERTICAL
);
325 sizerCol2
->Add(new wxStaticText(p
, wxID_ANY
, _T("Growable middle row and column:")), 0, wxCENTER
| wxTOP
, 20);
326 sizerFlex
= new wxFlexGridSizer(3, 3);
327 InitFlexSizer(sizerFlex
, p
);
328 sizerFlex
->AddGrowableCol(1);
329 sizerFlex
->AddGrowableRow(1);
330 sizerCol2
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
332 sizerCol2
->Add(new wxStaticText(p
, wxID_ANY
, _T("Same with horz flex direction")), 0, wxCENTER
| wxTOP
, 20);
333 sizerFlex
= new wxFlexGridSizer(3, 3);
334 InitFlexSizer(sizerFlex
, p
);
335 sizerFlex
->AddGrowableCol(1);
336 sizerFlex
->AddGrowableRow(1);
337 sizerFlex
->SetFlexibleDirection(wxHORIZONTAL
);
338 sizerCol2
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
340 sizerCol2
->Add(new wxStaticText(p
, wxID_ANY
, _T("Same with grow mode == \"none\"")), 0, wxCENTER
| wxTOP
, 20);
341 sizerFlex
= new wxFlexGridSizer(3, 3);
342 InitFlexSizer(sizerFlex
, p
);
343 sizerFlex
->AddGrowableCol(1);
344 sizerFlex
->AddGrowableRow(1);
345 sizerFlex
->SetFlexibleDirection(wxHORIZONTAL
);
346 sizerFlex
->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_NONE
);
347 sizerCol2
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
349 sizerCol2
->Add(new wxStaticText(p
, wxID_ANY
, _T("Same with grow mode == \"all\"")), 0, wxCENTER
| wxTOP
, 20);
350 sizerFlex
= new wxFlexGridSizer(3, 3);
351 InitFlexSizer(sizerFlex
, p
);
352 sizerFlex
->AddGrowableCol(1);
353 sizerFlex
->AddGrowableRow(1);
354 sizerFlex
->SetFlexibleDirection(wxHORIZONTAL
);
355 sizerFlex
->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL
);
356 sizerCol2
->Add(sizerFlex
, 1, wxALL
| wxEXPAND
, 10);
358 // add both columns to grid sizer
359 wxGridSizer
*sizerTop
= new wxGridSizer(2, 0, 20);
360 sizerTop
->Add(sizerCol1
, 1, wxEXPAND
);
361 sizerTop
->Add(sizerCol2
, 1, wxEXPAND
);
363 p
->SetSizer(sizerTop
);
364 sizerTop
->SetSizeHints(this);
367 // ----------------------------------------------------------------------------
369 // ----------------------------------------------------------------------------
371 MySizerDialog::MySizerDialog(wxWindow
*parent
, const wxChar
*title
)
372 : wxDialog(parent
, wxID_ANY
, wxString(title
))
374 // Begin with first hierarchy: a notebook at the top and
375 // and OK button at the bottom.
377 wxBoxSizer
*topsizer
= new wxBoxSizer( wxVERTICAL
);
379 wxNotebook
*notebook
= new wxNotebook( this, wxID_ANY
);
380 topsizer
->Add( notebook
, 1, wxGROW
);
382 wxButton
*button
= new wxButton( this, wxID_OK
, _T("OK") );
383 topsizer
->Add( button
, 0, wxALIGN_RIGHT
| wxALL
, 10 );
385 // First page: one big text ctrl
386 wxTextCtrl
*multi
= new wxTextCtrl( notebook
, wxID_ANY
, _T("TextCtrl."), wxDefaultPosition
, wxDefaultSize
, wxTE_MULTILINE
);
387 notebook
->AddPage( multi
, _T("Page One") );
389 // Second page: a text ctrl and a button
390 wxPanel
*panel
= new wxPanel( notebook
, wxID_ANY
);
391 notebook
->AddPage( panel
, _T("Page Two") );
393 wxSizer
*panelsizer
= new wxBoxSizer( wxVERTICAL
);
395 wxTextCtrl
*text
= new wxTextCtrl( panel
, wxID_ANY
, _T("TextLine 1."), wxDefaultPosition
, wxSize(250,-1) );
396 panelsizer
->Add( text
, 0, wxGROW
|wxALL
, 30 );
397 text
= new wxTextCtrl( panel
, wxID_ANY
, _T("TextLine 2."), wxDefaultPosition
, wxSize(250,-1) );
398 panelsizer
->Add( text
, 0, wxGROW
|wxALL
, 30 );
399 wxButton
*button2
= new wxButton( panel
, wxID_ANY
, _T("Hallo") );
400 panelsizer
->Add( button2
, 0, wxALIGN_RIGHT
| wxLEFT
|wxRIGHT
|wxBOTTOM
, 30 );
402 panel
->SetAutoLayout( true );
403 panel
->SetSizer( panelsizer
);
405 // Tell dialog to use sizer
406 SetSizer( topsizer
);
407 topsizer
->SetSizeHints( this );
410 // ----------------------------------------------------------------------------
411 // MyGridBagSizerFrame
412 // ----------------------------------------------------------------------------
414 // some simple macros to help make the sample code below more clear
415 #define TEXTCTRL(text) new wxTextCtrl(p, wxID_ANY, _T(text))
416 #define MLTEXTCTRL(text) new wxTextCtrl(p, wxID_ANY, _T(text), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE)
417 #define POS(r, c) wxGBPosition(r,c)
418 #define SPAN(r, c) wxGBSpan(r,c)
420 const wxChar gbsDescription
[] =_T("\
421 The wxGridBagSizer is similar to the wxFlexGridSizer except the items are explicitly positioned\n\
422 in a virtual cell of the layout grid, and column or row spanning is allowed. For example, this\n\
423 static text is positioned at (0,0) and it spans 7 columns.");
437 BEGIN_EVENT_TABLE(MyGridBagSizerFrame
, wxFrame
)
438 EVT_BUTTON( GBS_HIDE_BTN
, MyGridBagSizerFrame::OnHideBtn
)
439 EVT_BUTTON( GBS_SHOW_BTN
, MyGridBagSizerFrame::OnShowBtn
)
440 EVT_BUTTON( GBS_MOVE_BTN1
, MyGridBagSizerFrame::OnMoveBtn
)
441 EVT_BUTTON( GBS_MOVE_BTN2
, MyGridBagSizerFrame::OnMoveBtn
)
445 MyGridBagSizerFrame::MyGridBagSizerFrame(const wxChar
*title
, int x
, int y
)
446 : wxFrame( NULL
, wxID_ANY
, title
, wxPoint(x
, y
) )
448 wxPanel
* p
= new wxPanel(this, wxID_ANY
);
450 m_gbs
= new wxGridBagSizer();
453 m_gbs
->Add( new wxStaticText(p
, wxID_ANY
, gbsDescription
),
454 POS(0,0), SPAN(1, 7),
455 wxALIGN_CENTER
| wxALL
, 5);
457 m_gbs
->Add( TEXTCTRL("pos(1,0)"), POS(1,0) );
458 m_gbs
->Add( TEXTCTRL("pos(1,1)"), POS(1,1) );
459 m_gbs
->Add( TEXTCTRL("pos(2,0)"), POS(2,0) );
460 m_gbs
->Add( TEXTCTRL("pos(2,1)"), POS(2,1) );
461 m_gbs
->Add( MLTEXTCTRL("pos(3,2), span(1,2)\nthis row and col are growable"),
462 POS(3,2), SPAN(1,2), wxEXPAND
);
463 m_gbs
->Add( MLTEXTCTRL("pos(4,3)\nspan(3,1)"),
464 POS(4,3), SPAN(3,1), wxEXPAND
);
465 m_gbs
->Add( TEXTCTRL("pos(5,4)"), POS(5,4), wxDefaultSpan
, wxEXPAND
);
466 m_gbs
->Add( TEXTCTRL("pos(6,5)"), POS(6,5), wxDefaultSpan
, wxEXPAND
);
467 m_gbs
->Add( TEXTCTRL("pos(7,6)"), POS(7,6) );
469 //m_gbs->Add( TEXTCTRL("bad position"), POS(4,3) ); // Test for assert
470 //m_gbs->Add( TEXTCTRL("bad position"), POS(5,3) ); // Test for assert
473 m_moveBtn1
= new wxButton(p
, GBS_MOVE_BTN1
, _T("Move this to (3,6)"));
474 m_moveBtn2
= new wxButton(p
, GBS_MOVE_BTN2
, _T("Move this to (3,6)"));
475 m_gbs
->Add( m_moveBtn1
, POS(10,2) );
476 m_gbs
->Add( m_moveBtn2
, POS(10,3) );
478 m_hideBtn
= new wxButton(p
, GBS_HIDE_BTN
, _T("Hide this item -->"));
479 m_gbs
->Add(m_hideBtn
, POS(12, 3));
481 m_hideTxt
= new wxTextCtrl(p
, wxID_ANY
, _T("pos(12,4), size(150, -1)"),
482 wxDefaultPosition
, wxSize(150,-1));
483 m_gbs
->Add( m_hideTxt
, POS(12,4) );
485 m_showBtn
= new wxButton(p
, GBS_SHOW_BTN
, _T("<-- Show it again"));
486 m_gbs
->Add(m_showBtn
, POS(12, 5));
487 m_showBtn
->Disable();
489 m_gbs
->Add(10,10, POS(14,0));
491 m_gbs
->AddGrowableRow(3);
492 m_gbs
->AddGrowableCol(2);
494 p
->SetSizerAndFit(m_gbs
);
495 SetClientSize(p
->GetSize());
499 void MyGridBagSizerFrame::OnHideBtn(wxCommandEvent
&)
501 m_gbs
->Hide(m_hideTxt
);
502 m_hideBtn
->Disable();
507 void MyGridBagSizerFrame::OnShowBtn(wxCommandEvent
&)
509 m_gbs
->Show(m_hideTxt
);
511 m_showBtn
->Disable();
516 void MyGridBagSizerFrame::OnMoveBtn(wxCommandEvent
& event
)
518 wxButton
* btn
= (wxButton
*)event
.GetEventObject();
519 wxGBPosition curPos
= m_gbs
->GetItemPosition(btn
);
521 // if it's already at the "other" spot then move it back
522 if (curPos
== wxGBPosition(3,6))
524 m_gbs
->SetItemPosition(btn
, m_lastPos
);
525 btn
->SetLabel(_T("Move this to (3,6)"));
529 if ( m_gbs
->CheckForIntersection(wxGBPosition(3,6), wxGBSpan(1,1)) )
531 _T("wxGridBagSizer will not allow items to be in the same cell as\n\
532 another item, so this operation will fail. You will also get an assert\n\
533 when compiled in debug mode."), _T("Warning"), wxOK
| wxICON_INFORMATION
);
535 if ( m_gbs
->SetItemPosition(btn
, wxGBPosition(3,6)) )
538 btn
->SetLabel(_T("Move it back"));