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