Fixes for wxUSE_STATUSBAR.
[wxWidgets.git] / samples / layout / layout.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: layout.cpp
3 // Purpose: Layout sample
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ----------------------------------------------------------------------------
13 // headers
14 // ----------------------------------------------------------------------------
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/sizer.h"
28 #include "wx/gbsizer.h"
29 #include "wx/statline.h"
30 #include "wx/notebook.h"
31
32 #include "layout.h"
33
34 // ----------------------------------------------------------------------------
35 // MyApp
36 // ----------------------------------------------------------------------------
37
38 IMPLEMENT_APP(MyApp)
39
40 MyApp::MyApp()
41 {
42 }
43
44 bool MyApp::OnInit()
45 {
46 // Create the main frame window
47 MyFrame *frame = new MyFrame;
48
49 frame->Show(true);
50
51 return true;
52 }
53
54 // ----------------------------------------------------------------------------
55 // MyFrame
56 // ----------------------------------------------------------------------------
57
58 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
59 EVT_MENU(LAYOUT_ABOUT, MyFrame::OnAbout)
60 EVT_MENU(LAYOUT_QUIT, MyFrame::OnQuit)
61
62 EVT_MENU(LAYOUT_TEST_SIZER, MyFrame::TestFlexSizers)
63 EVT_MENU(LAYOUT_TEST_NB_SIZER, MyFrame::TestNotebookSizers)
64 EVT_MENU(LAYOUT_TEST_GB_SIZER, MyFrame::TestGridBagSizer)
65 END_EVENT_TABLE()
66
67 // Define my frame constructor
68 MyFrame::MyFrame()
69 : wxFrame(NULL, wxID_ANY, _T("wxWidgets Layout Demo"),
70 wxDefaultPosition, wxDefaultSize,
71 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
72 {
73 // Make a menubar
74 wxMenu *file_menu = new wxMenu;
75
76 file_menu->Append(LAYOUT_TEST_SIZER, _T("Test wx&FlexSizer"));
77 file_menu->Append(LAYOUT_TEST_NB_SIZER, _T("&Test notebook sizers"));
78 file_menu->Append(LAYOUT_TEST_GB_SIZER, _T("Test &gridbag sizer"));
79
80 file_menu->AppendSeparator();
81 file_menu->Append(LAYOUT_QUIT, _T("E&xit"), _T("Quit program"));
82
83 wxMenu *help_menu = new wxMenu;
84 help_menu->Append(LAYOUT_ABOUT, _T("&About"), _T("About layout demo"));
85
86 wxMenuBar *menu_bar = new wxMenuBar;
87
88 menu_bar->Append(file_menu, _T("&File"));
89 menu_bar->Append(help_menu, _T("&Help"));
90
91 // Associate the menu bar with the frame
92 SetMenuBar(menu_bar);
93
94 #if wxUSE_STATUSBAR
95 CreateStatusBar(2);
96 SetStatusText(_T("wxWidgets layout demo"));
97 #endif // wxUSE_STATUSBAR
98
99 // we want to get a dialog that is stretchable because it
100 // has a text ctrl in the middle. at the bottom, we have
101 // two buttons which.
102
103 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
104
105 // 1) top: create wxStaticText with minimum size equal to its default size
106 topsizer->Add(
107 new wxStaticText( this, wxID_ANY, _T("An explanation (wxALIGN_RIGHT).") ),
108 0, // make vertically unstretchable
109 wxALIGN_RIGHT | // right align text
110 wxTOP | wxLEFT | wxRIGHT, // make border all around except wxBOTTOM
111 5 ); // set border width to 5
112
113 // 2) top: create wxTextCtrl with minimum size (100x60)
114 topsizer->Add(
115 new wxTextCtrl( this, wxID_ANY, _T("My text (wxEXPAND)."), wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE),
116 1, // make vertically stretchable
117 wxEXPAND | // make horizontally stretchable
118 wxALL, // and make border all around
119 5 ); // set border width to 5
120
121 // 2.5) Gratuitous test of wxStaticBoxSizers
122 wxBoxSizer *statsizer = new wxStaticBoxSizer(
123 new wxStaticBox(this, wxID_ANY, _T("A wxStaticBoxSizer")),
124 wxVERTICAL );
125 statsizer->Add(
126 new wxStaticText(this, wxID_ANY, _T("And some TEXT inside it")),
127 0,
128 wxCENTER |
129 wxALL,
130 30);
131 topsizer->Add(statsizer, 1, wxEXPAND | wxALL, 10);
132
133 // 2.7) And a test of wxGridSizer
134 wxGridSizer *gridsizer = new wxGridSizer(2, 5, 5);
135 gridsizer->Add(new wxStaticText(this, wxID_ANY, _T("Label")), 0,
136 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
137 gridsizer->Add(new wxTextCtrl(this, wxID_ANY, _T("Grid sizer demo")), 1,
138 wxGROW | wxALIGN_CENTER_VERTICAL);
139 gridsizer->Add(new wxStaticText(this, wxID_ANY, _T("Another label")), 0,
140 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
141 gridsizer->Add(new wxTextCtrl(this, wxID_ANY, _T("More text")), 1,
142 wxGROW | wxALIGN_CENTER_VERTICAL);
143 gridsizer->Add(new wxStaticText(this, wxID_ANY, _T("Final label")), 0,
144 wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
145 gridsizer->Add(new wxTextCtrl(this, wxID_ANY, _T("And yet more text")), 1,
146 wxGROW | wxALIGN_CENTER_VERTICAL);
147 topsizer->Add(gridsizer, 1, wxGROW | wxALL, 10);
148
149
150 // 3) middle: create wxStaticLine with minimum size (3x3)
151 topsizer->Add(
152 new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL),
153 0, // make vertically unstretchable
154 wxEXPAND | // make horizontally stretchable
155 wxALL, // and make border all around
156 5 ); // set border width to 5
157
158
159 // 4) bottom: create two centred wxButtons
160 wxBoxSizer *button_box = new wxBoxSizer( wxHORIZONTAL );
161 button_box->Add(
162 new wxButton( this, wxID_ANY, _T("Two buttons in a box") ),
163 0, // make horizontally unstretchable
164 wxALL, // make border all around
165 7 ); // set border width to 7
166 button_box->Add(
167 new wxButton( this, wxID_ANY, _T("(wxCENTER)") ),
168 0, // make horizontally unstretchable
169 wxALL, // make border all around
170 7 ); // set border width to 7
171
172 topsizer->Add(
173 button_box,
174 0, // make vertically unstretchable
175 wxCENTER ); // no border and centre horizontally
176
177 // don't allow frame to get smaller than what the sizers tell it and also set
178 // the initial size as calculated by the sizers
179 topsizer->SetSizeHints( this );
180
181 SetSizer( topsizer );
182 }
183
184 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
185 {
186 Close(true);
187 }
188
189 void MyFrame::TestFlexSizers(wxCommandEvent& WXUNUSED(event) )
190 {
191 MyFlexSizerFrame *newFrame = new MyFlexSizerFrame(_T("Flex Sizer Test Frame"), 50, 50);
192 newFrame->Show(true);
193 }
194
195 void MyFrame::TestNotebookSizers(wxCommandEvent& WXUNUSED(event) )
196 {
197 MySizerDialog dialog( this, _T("Notebook Sizer Test Dialog") );
198
199 dialog.ShowModal();
200 }
201
202
203 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
204 {
205 (void)wxMessageBox(_T("wxWidgets GUI library layout demo\n"),
206 _T("About Layout Demo"), wxOK|wxICON_INFORMATION);
207 }
208
209 void MyFrame::TestGridBagSizer(wxCommandEvent& WXUNUSED(event) )
210 {
211 MyGridBagSizerFrame *newFrame = new
212 MyGridBagSizerFrame(_T("wxGridBagSizer Test Frame"), 50, 50);
213 newFrame->Show(true);
214 }
215
216
217 // ----------------------------------------------------------------------------
218 // MyFlexSizerFrame
219 // ----------------------------------------------------------------------------
220
221 void MyFlexSizerFrame::InitFlexSizer(wxFlexGridSizer *sizer)
222 {
223 for ( int i = 0; i < 3; i++ )
224 {
225 for ( int j = 0; j < 3; j++ )
226 {
227 sizer->Add(new wxStaticText
228 (
229 this,
230 wxID_ANY,
231 wxString::Format(_T("(%d, %d)"), i + 1, j + 1),
232 wxDefaultPosition,
233 wxDefaultSize,
234 wxALIGN_CENTER
235 ),
236 0, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 3);
237 }
238 }
239 }
240
241 MyFlexSizerFrame::MyFlexSizerFrame(const wxChar *title, int x, int y )
242 : wxFrame(NULL, wxID_ANY, title, wxPoint(x, y) )
243 {
244 wxFlexGridSizer *sizerFlex;
245
246 // consttuct the first column
247 wxSizer *sizerCol1 = new wxBoxSizer(wxVERTICAL);
248 sizerCol1->Add(new wxStaticText(this, wxID_ANY, _T("Ungrowable:")), 0, wxCENTER | wxTOP, 20);
249 sizerFlex = new wxFlexGridSizer(3, 3);
250 InitFlexSizer(sizerFlex);
251 sizerCol1->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
252
253 sizerCol1->Add(new wxStaticText(this, wxID_ANY, _T("Growable middle column:")), 0, wxCENTER | wxTOP, 20);
254 sizerFlex = new wxFlexGridSizer(3, 3);
255 InitFlexSizer(sizerFlex);
256 sizerFlex->AddGrowableCol(1);
257 sizerCol1->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
258
259 sizerCol1->Add(new wxStaticText(this, wxID_ANY, _T("Growable middle row:")), 0, wxCENTER | wxTOP, 20);
260 sizerFlex = new wxFlexGridSizer(3, 3);
261 InitFlexSizer(sizerFlex);
262 sizerFlex->AddGrowableRow(1);
263 sizerCol1->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
264
265 sizerCol1->Add(new wxStaticText(this, wxID_ANY, _T("All growable columns:")), 0, wxCENTER | wxTOP, 20);
266 sizerFlex = new wxFlexGridSizer(3, 3);
267 InitFlexSizer(sizerFlex);
268 sizerFlex->AddGrowableCol(0, 1);
269 sizerFlex->AddGrowableCol(1, 2);
270 sizerFlex->AddGrowableCol(2, 3);
271 sizerCol1->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
272
273 // the second one
274 wxSizer *sizerCol2 = new wxBoxSizer(wxVERTICAL);
275 sizerCol2->Add(new wxStaticText(this, wxID_ANY, _T("Growable middle row and column:")), 0, wxCENTER | wxTOP, 20);
276 sizerFlex = new wxFlexGridSizer(3, 3);
277 InitFlexSizer(sizerFlex);
278 sizerFlex->AddGrowableCol(1);
279 sizerFlex->AddGrowableRow(1);
280 sizerCol2->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
281
282 sizerCol2->Add(new wxStaticText(this, wxID_ANY, _T("Same with horz flex direction")), 0, wxCENTER | wxTOP, 20);
283 sizerFlex = new wxFlexGridSizer(3, 3);
284 InitFlexSizer(sizerFlex);
285 sizerFlex->AddGrowableCol(1);
286 sizerFlex->AddGrowableRow(1);
287 sizerFlex->SetFlexibleDirection(wxHORIZONTAL);
288 sizerCol2->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
289
290 sizerCol2->Add(new wxStaticText(this, wxID_ANY, _T("Same with grow mode == \"none\"")), 0, wxCENTER | wxTOP, 20);
291 sizerFlex = new wxFlexGridSizer(3, 3);
292 InitFlexSizer(sizerFlex);
293 sizerFlex->AddGrowableCol(1);
294 sizerFlex->AddGrowableRow(1);
295 sizerFlex->SetFlexibleDirection(wxHORIZONTAL);
296 sizerFlex->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_NONE);
297 sizerCol2->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
298
299 sizerCol2->Add(new wxStaticText(this, wxID_ANY, _T("Same with grow mode == \"all\"")), 0, wxCENTER | wxTOP, 20);
300 sizerFlex = new wxFlexGridSizer(3, 3);
301 InitFlexSizer(sizerFlex);
302 sizerFlex->AddGrowableCol(1);
303 sizerFlex->AddGrowableRow(1);
304 sizerFlex->SetFlexibleDirection(wxHORIZONTAL);
305 sizerFlex->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
306 sizerCol2->Add(sizerFlex, 1, wxALL | wxEXPAND, 10);
307
308 // add both columns to grid sizer
309 wxGridSizer *sizerTop = new wxGridSizer(2, 0, 20);
310 sizerTop->Add(sizerCol1, 1, wxEXPAND);
311 sizerTop->Add(sizerCol2, 1, wxEXPAND);
312
313 SetSizer(sizerTop);
314 sizerTop->SetSizeHints(this);
315 }
316
317 // ----------------------------------------------------------------------------
318 // MySizerDialog
319 // ----------------------------------------------------------------------------
320
321 MySizerDialog::MySizerDialog(wxWindow *parent, const wxChar *title)
322 : wxDialog(parent, wxID_ANY, wxString(title))
323 {
324 // Begin with first hierarchy: a notebook at the top and
325 // and OK button at the bottom.
326
327 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
328
329 wxNotebook *notebook = new wxNotebook( this, wxID_ANY );
330 topsizer->Add( notebook, 1, wxGROW );
331
332 wxButton *button = new wxButton( this, wxID_OK, _T("OK") );
333 topsizer->Add( button, 0, wxALIGN_RIGHT | wxALL, 10 );
334
335 // First page: one big text ctrl
336 wxTextCtrl *multi = new wxTextCtrl( notebook, wxID_ANY, _T("TextCtrl."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
337 notebook->AddPage( multi, _T("Page One") );
338
339 // Second page: a text ctrl and a button
340 wxPanel *panel = new wxPanel( notebook, wxID_ANY );
341 notebook->AddPage( panel, _T("Page Two") );
342
343 wxSizer *panelsizer = new wxBoxSizer( wxVERTICAL );
344
345 wxTextCtrl *text = new wxTextCtrl( panel, wxID_ANY, _T("TextLine 1."), wxDefaultPosition, wxSize(250,-1) );
346 panelsizer->Add( text, 0, wxGROW|wxALL, 30 );
347 text = new wxTextCtrl( panel, wxID_ANY, _T("TextLine 2."), wxDefaultPosition, wxSize(250,-1) );
348 panelsizer->Add( text, 0, wxGROW|wxALL, 30 );
349 wxButton *button2 = new wxButton( panel, wxID_ANY, _T("Hallo") );
350 panelsizer->Add( button2, 0, wxALIGN_RIGHT | wxLEFT|wxRIGHT|wxBOTTOM, 30 );
351
352 panel->SetAutoLayout( true );
353 panel->SetSizer( panelsizer );
354
355 // Tell dialog to use sizer
356 SetSizer( topsizer );
357 topsizer->SetSizeHints( this );
358 }
359
360 // ----------------------------------------------------------------------------
361 // MyGridBagSizerFrame
362 // ----------------------------------------------------------------------------
363
364 // some simple macros to help make the sample code below more clear
365 #define TEXTCTRL(text) new wxTextCtrl(p, wxID_ANY, _T(text))
366 #define MLTEXTCTRL(text) new wxTextCtrl(p, wxID_ANY, _T(text), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE)
367 #define POS(r, c) wxGBPosition(r,c)
368 #define SPAN(r, c) wxGBSpan(r,c)
369
370 wxChar* gbsDescription =_T("\
371 The wxGridBagSizer is similar to the wxFlexGridSizer except the items are explicitly positioned\n\
372 in a virtual cell of the layout grid, and column or row spanning is allowed. For example, this\n\
373 static text is positioned at (0,0) and it spans 7 columns.");
374
375
376 // Some IDs
377 enum {
378 GBS_HIDE_BTN = 1212,
379 GBS_SHOW_BTN,
380 GBS_MOVE_BTN1,
381 GBS_MOVE_BTN2,
382
383 GBS_MAX,
384 };
385
386
387 BEGIN_EVENT_TABLE(MyGridBagSizerFrame, wxFrame)
388 EVT_BUTTON( GBS_HIDE_BTN, MyGridBagSizerFrame::OnHideBtn)
389 EVT_BUTTON( GBS_SHOW_BTN, MyGridBagSizerFrame::OnShowBtn)
390 EVT_BUTTON( GBS_MOVE_BTN1, MyGridBagSizerFrame::OnMoveBtn)
391 EVT_BUTTON( GBS_MOVE_BTN2, MyGridBagSizerFrame::OnMoveBtn)
392 END_EVENT_TABLE()
393
394
395 MyGridBagSizerFrame::MyGridBagSizerFrame(const wxChar *title, int x, int y )
396 : wxFrame( NULL, wxID_ANY, title, wxPoint(x, y) )
397 {
398 wxPanel* p = new wxPanel(this, wxID_ANY);
399 m_panel = p;
400 m_gbs = new wxGridBagSizer();
401
402
403 m_gbs->Add( new wxStaticText(p, wxID_ANY, gbsDescription),
404 POS(0,0), SPAN(1, 7),
405 wxALIGN_CENTER | wxALL, 5);
406
407 m_gbs->Add( TEXTCTRL("pos(1,0)"), POS(1,0) );
408 m_gbs->Add( TEXTCTRL("pos(1,1)"), POS(1,1) );
409 m_gbs->Add( TEXTCTRL("pos(2,0)"), POS(2,0) );
410 m_gbs->Add( TEXTCTRL("pos(2,1)"), POS(2,1) );
411 m_gbs->Add( MLTEXTCTRL("pos(3,2), span(1,2)\nthis row and col are growable"),
412 POS(3,2), SPAN(1,2), wxEXPAND );
413 m_gbs->Add( MLTEXTCTRL("pos(4,3)\nspan(3,1)"),
414 POS(4,3), SPAN(3,1), wxEXPAND );
415 m_gbs->Add( TEXTCTRL("pos(5,4)"), POS(5,4), wxDefaultSpan, wxEXPAND );
416 m_gbs->Add( TEXTCTRL("pos(6,5)"), POS(6,5), wxDefaultSpan, wxEXPAND );
417 m_gbs->Add( TEXTCTRL("pos(7,6)"), POS(7,6) );
418
419 //m_gbs->Add( TEXTCTRL("bad position"), POS(4,3) ); // Test for assert
420 //m_gbs->Add( TEXTCTRL("bad position"), POS(5,3) ); // Test for assert
421
422
423 m_moveBtn1 = new wxButton(p, GBS_MOVE_BTN1, _T("Move this to (3,6)"));
424 m_moveBtn2 = new wxButton(p, GBS_MOVE_BTN2, _T("Move this to (3,6)"));
425 m_gbs->Add( m_moveBtn1, POS(10,2) );
426 m_gbs->Add( m_moveBtn2, POS(10,3) );
427
428 m_hideBtn = new wxButton(p, GBS_HIDE_BTN, _T("Hide this item -->"));
429 m_gbs->Add(m_hideBtn, POS(12, 3));
430
431 m_hideTxt = new wxTextCtrl(p, wxID_ANY, _T("pos(12,4), size(150, -1)"),
432 wxDefaultPosition, wxSize(150,-1));
433 m_gbs->Add( m_hideTxt, POS(12,4) );
434
435 m_showBtn = new wxButton(p, GBS_SHOW_BTN, _T("<-- Show it again"));
436 m_gbs->Add(m_showBtn, POS(12, 5));
437 m_showBtn->Disable();
438
439 m_gbs->Add(10,10, POS(14,0));
440
441 m_gbs->AddGrowableRow(3);
442 m_gbs->AddGrowableCol(2);
443
444 p->SetSizerAndFit(m_gbs);
445 SetClientSize(p->GetSize());
446 }
447
448
449 void MyGridBagSizerFrame::OnHideBtn(wxCommandEvent&)
450 {
451 m_gbs->Hide(m_hideTxt);
452 m_hideBtn->Disable();
453 m_showBtn->Enable();
454 m_gbs->Layout();
455 }
456
457 void MyGridBagSizerFrame::OnShowBtn(wxCommandEvent&)
458 {
459 m_gbs->Show(m_hideTxt);
460 m_hideBtn->Enable();
461 m_showBtn->Disable();
462 m_gbs->Layout();
463 }
464
465
466 void MyGridBagSizerFrame::OnMoveBtn(wxCommandEvent& event)
467 {
468 wxButton* btn = (wxButton*)event.GetEventObject();
469 wxGBPosition curPos = m_gbs->GetItemPosition(btn);
470
471 // if it's already at the "other" spot then move it back
472 if (curPos == wxGBPosition(3,6))
473 {
474 m_gbs->SetItemPosition(btn, m_lastPos);
475 btn->SetLabel(_T("Move this to (3,6)"));
476 }
477 else
478 {
479 if ( m_gbs->CheckForIntersection(wxGBPosition(3,6), wxGBSpan(1,1)) )
480 wxMessageBox(
481 _T("wxGridBagSizer will not allow items to be in the same cell as\n\
482 another item, so this operation will fail. You will also get an assert\n\
483 when compiled in debug mode."), _T("Warning"), wxOK | wxICON_INFORMATION);
484
485 if ( m_gbs->SetItemPosition(btn, wxGBPosition(3,6)) )
486 {
487 m_lastPos = curPos;
488 btn->SetLabel(_T("Move it back"));
489 }
490 }
491 m_gbs->Layout();
492 }