Completed wxBox,
[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 and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #if !wxUSE_CONSTRAINTS
24 #error You must set wxUSE_CONSTRAINTS to 1 in setup.h!
25 #endif
26
27 #include <ctype.h>
28 #include "wx/sizer.h"
29 #include "wx/statline.h"
30
31 #include "layout.h"
32
33 // Declare two frames
34 MyFrame *frame = (MyFrame *) NULL;
35 wxMenuBar *menu_bar = (wxMenuBar *) NULL;
36
37 IMPLEMENT_APP(MyApp)
38
39 MyApp::MyApp()
40 {
41 }
42
43 bool MyApp::OnInit(void)
44 {
45 // Create the main frame window
46 frame = new MyFrame((MyFrame *) NULL, (char *) "wxWindows Layout Demo", 0, 0, 550, 500);
47
48 frame->SetAutoLayout(TRUE);
49
50 // Give it a status line
51 frame->CreateStatusBar(2);
52
53 // Make a menubar
54 wxMenu *file_menu = new wxMenu;
55
56 file_menu->Append(LAYOUT_LOAD_FILE, "&Load file", "Load a text file");
57 file_menu->Append(LAYOUT_TEST, "&Test sizers", "Test sizer code");
58 file_menu->Append(LAYOUT_TEST_NEW, "&Test new sizers", "Test new sizer code");
59
60 file_menu->AppendSeparator();
61 file_menu->Append(LAYOUT_QUIT, "E&xit", "Quit program");
62
63 wxMenu *help_menu = new wxMenu;
64 help_menu->Append(LAYOUT_ABOUT, "&About", "About layout demo");
65
66 menu_bar = new wxMenuBar;
67
68 menu_bar->Append(file_menu, "&File");
69 menu_bar->Append(help_menu, "&Help");
70
71 // Associate the menu bar with the frame
72 frame->SetMenuBar(menu_bar);
73
74 // Make a panel
75 frame->panel = new wxPanel(frame, 0, 0, 1000, 500, wxTAB_TRAVERSAL);
76 frame->panel->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
77 // frame->panel->SetAutoLayout(TRUE);
78
79 // Create some panel items
80 wxButton *btn1 = new wxButton(frame->panel, -1, "A button (1)") ;
81
82 wxLayoutConstraints *b1 = new wxLayoutConstraints;
83 b1->centreX.SameAs (frame->panel, wxCentreX);
84 b1->top.SameAs (frame->panel, wxTop, 5);
85 b1->width.PercentOf (frame->panel, wxWidth, 80);
86 b1->height.PercentOf (frame->panel, wxHeight, 10);
87 btn1->SetConstraints(b1);
88
89 wxListBox *list = new wxListBox(frame->panel, -1,
90 wxPoint(-1, -1), wxSize(200, 100));
91 list->Append("Apple");
92 list->Append("Pear");
93 list->Append("Orange");
94 list->Append("Banana");
95 list->Append("Fruit");
96
97 wxLayoutConstraints *b2 = new wxLayoutConstraints;
98 b2->top.Below (btn1, 5);
99 b2->left.SameAs (frame->panel, wxLeft, 5);
100 b2->width.PercentOf (frame->panel, wxWidth, 40);
101 b2->bottom.SameAs (frame->panel, wxBottom, 5);
102 list->SetConstraints(b2);
103
104 wxTextCtrl *mtext = new wxTextCtrl(frame->panel, -1, "Some text",
105 wxPoint(-1, -1), wxSize(150, 100));
106
107 wxLayoutConstraints *b3 = new wxLayoutConstraints;
108 b3->top.Below (btn1, 5);
109 b3->left.RightOf (list, 5);
110 b3->right.SameAs (frame->panel, wxRight, 5);
111 b3->bottom.SameAs (frame->panel, wxBottom, 5);
112 mtext->SetConstraints(b3);
113
114 frame->canvas = new MyWindow(frame, 0, 0, 400, 400, wxRETAINED);
115
116 // Give it scrollbars: the virtual canvas is 20 * 50 = 1000 pixels in each direction
117 // canvas->SetScrollbars(20, 20, 50, 50, 4, 4);
118
119 // Make a text window
120 frame->text_window = new MyTextWindow(frame, 0, 250, 400, 250);
121
122 // Set constraints for panel subwindow
123 wxLayoutConstraints *c1 = new wxLayoutConstraints;
124
125 c1->left.SameAs (frame, wxLeft);
126 c1->top.SameAs (frame, wxTop);
127 c1->right.PercentOf (frame, wxWidth, 50);
128 c1->height.PercentOf (frame, wxHeight, 50);
129
130 frame->panel->SetConstraints(c1);
131
132 // Set constraints for canvas subwindow
133 wxLayoutConstraints *c2 = new wxLayoutConstraints;
134
135 c2->left.SameAs (frame->panel, wxRight);
136 c2->top.SameAs (frame, wxTop);
137 c2->right.SameAs (frame, wxRight);
138 c2->height.PercentOf (frame, wxHeight, 50);
139
140 frame->canvas->SetConstraints(c2);
141
142 // Set constraints for text subwindow
143 wxLayoutConstraints *c3 = new wxLayoutConstraints;
144 c3->left.SameAs (frame, wxLeft);
145 c3->top.Below (frame->panel);
146 c3->right.SameAs (frame, wxRight);
147 c3->bottom.SameAs (frame, wxBottom);
148
149 frame->text_window->SetConstraints(c3);
150
151 frame->Show(TRUE);
152
153 frame->SetStatusText("wxWindows layout demo");
154
155 SetTopWindow(frame);
156 return TRUE;
157 }
158
159 //-----------------------------------------------------------------
160 // MyFrame
161 //-----------------------------------------------------------------
162
163 // Define my frame constructor
164 MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
165 wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h))
166 {
167 panel = (wxPanel *) NULL;
168 text_window = (MyTextWindow *) NULL;
169 canvas = (MyWindow *) NULL;
170 }
171
172 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
173 EVT_MENU(LAYOUT_LOAD_FILE, MyFrame::LoadFile)
174 EVT_MENU(LAYOUT_QUIT, MyFrame::Quit)
175 EVT_MENU(LAYOUT_TEST, MyFrame::TestSizers)
176 EVT_MENU(LAYOUT_TEST_NEW, MyFrame::TestNewSizers)
177 EVT_MENU(LAYOUT_ABOUT, MyFrame::About)
178 EVT_SIZE(MyFrame::OnSize)
179 END_EVENT_TABLE()
180
181 void MyFrame::LoadFile(wxCommandEvent& WXUNUSED(event) )
182 {
183 wxString s = wxFileSelector( _T("Load text file"), (const wxChar *) NULL,
184 (const wxChar *) NULL, (const wxChar *) NULL, _T("*.txt") );
185 if (s != "")
186 {
187 #ifdef __WXMSW__
188 frame->text_window->LoadFile(s);
189 #endif
190 }
191 }
192
193 void MyFrame::Quit(wxCommandEvent& WXUNUSED(event) )
194 {
195 this->Close(TRUE);
196 }
197
198 void MyFrame::TestSizers(wxCommandEvent& WXUNUSED(event) )
199 {
200 SizerFrame *newFrame = new SizerFrame((MyFrame *) NULL, "Sizer Test Frame", 50, 50, 500, 500);
201 newFrame->Show(TRUE);
202 }
203
204 void MyFrame::TestNewSizers(wxCommandEvent& WXUNUSED(event) )
205 {
206 NewSizerFrame *newFrame = new NewSizerFrame((MyFrame *) NULL, "Sizer Test Frame", 50, 50 );
207 newFrame->Show(TRUE);
208 }
209
210 void MyFrame::About(wxCommandEvent& WXUNUSED(event) )
211 {
212 (void)wxMessageBox("wxWindows GUI library layout demo\n",
213 "About Layout Demo", wxOK|wxCENTRE);
214 }
215
216 // Size the subwindows when the frame is resized
217 void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event) )
218 {
219 Layout();
220 }
221
222 void MyFrame::Draw(wxDC& dc, bool WXUNUSED(draw_bitmaps) )
223 {
224 dc.SetPen(* wxGREEN_PEN);
225 dc.DrawLine(0, 0, 200, 200);
226 dc.DrawLine(200, 0, 0, 200);
227
228 dc.SetBrush(* wxCYAN_BRUSH);
229 dc.SetPen(* wxRED_PEN);
230
231 dc.DrawRectangle(100, 100, 100, 50);
232 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
233
234 dc.DrawEllipse(250, 250, 100, 50);
235 dc.DrawSpline(50, 200, 50, 100, 200, 10);
236 dc.DrawLine(50, 230, 200, 230);
237
238 dc.SetPen(* wxBLACK_PEN);
239 dc.DrawArc(50, 300, 100, 250, 100, 300 );
240 }
241
242 //-----------------------------------------------------------------
243 // MyWindow
244 //-----------------------------------------------------------------
245
246 BEGIN_EVENT_TABLE(MyWindow, wxWindow)
247 EVT_PAINT(MyWindow::OnPaint)
248 END_EVENT_TABLE()
249
250 // Define a constructor for my canvas
251 MyWindow::MyWindow(wxFrame *frame, int x, int y, int w, int h, long style):
252 wxWindow(frame, -1, wxPoint(x, y), wxSize(w, h), style)
253 {
254 }
255
256 MyWindow::~MyWindow(void)
257 {
258 }
259
260 // Define the repainting behaviour
261 void MyWindow::OnPaint(wxPaintEvent& WXUNUSED(event) )
262 {
263 wxPaintDC dc(this);
264 frame->Draw(dc,TRUE);
265 }
266
267 //-----------------------------------------------------------------
268 // SizerFrame
269 //-----------------------------------------------------------------
270
271 SizerFrame::SizerFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
272 wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h))
273 {
274 panel = new wxPanel(this, -1, wxPoint(0, 0), wxSize(-1, -1), wxTAB_TRAVERSAL);
275 panel->SetBackgroundColour(wxColour(192, 192, 192));
276
277 // A sizer to fit the whole panel, plus two sizers, one
278 // above the other. A button is centred on the lower
279 // sizer; a rowcol containing 3 buttons is centred on the upper
280 // sizer.
281 wxSizer *expandSizer = new wxSizer(panel, wxSizerExpand);
282 expandSizer->SetName("expandSizer");
283
284 wxLayoutConstraints *c;
285
286 /////// TOP OF PANEL
287 ///////
288 wxSizer *topSizer = new wxSizer(expandSizer);
289 topSizer->SetName("topSizer");
290
291 // Specify constraints for the top sizer
292 c = new wxLayoutConstraints;
293 c->left.SameAs (expandSizer, wxLeft);
294 c->top.SameAs (expandSizer, wxTop);
295 c->right.SameAs (expandSizer, wxRight);
296 c->height.PercentOf (expandSizer, wxHeight, 50);
297
298 topSizer->SetConstraints(c);
299
300 /*
301 * Add a row-col sizer and some buttons
302 */
303
304 // Default is layout by rows, 20 columns per row, shrink to fit.
305 wxRowColSizer *rowCol = new wxRowColSizer(topSizer);
306 rowCol->SetName("rowCol");
307
308 wxButton *button = new wxButton(panel, -1, "Button 1");
309 rowCol->AddSizerChild(button);
310
311 button = new wxButton(panel, -1, "Button 2");
312 rowCol->AddSizerChild(button);
313
314 button = new wxButton(panel, -1, "Button 3");
315 rowCol->AddSizerChild(button);
316
317 // Centre the rowcol in the middle of the upper sizer
318 c = new wxLayoutConstraints;
319 c->centreX.SameAs (topSizer, wxCentreX);
320 c->centreY.SameAs (topSizer, wxCentreY);
321 c->width.AsIs();
322 c->height.AsIs();
323 rowCol->SetConstraints(c);
324
325 /////// BOTTOM OF PANEL
326 ///////
327 wxSizer *bottomSizer = new wxSizer(expandSizer);
328
329 // Specify constraints for the bottom sizer
330 c = new wxLayoutConstraints;
331 c->left.SameAs (expandSizer, wxLeft);
332 c->top.PercentOf (expandSizer, wxHeight, 50);
333 c->right.SameAs (expandSizer, wxRight);
334 c->height.PercentOf (expandSizer, wxHeight, 50);
335
336 bottomSizer->SetConstraints(c);
337
338 wxButton *button2 = new wxButton(panel, -1, "Test button");
339
340 // The button should be a child of the bottom sizer
341 bottomSizer->AddSizerChild(button2);
342
343 // Centre the button on the sizer
344 c = new wxLayoutConstraints;
345 c->centreX.SameAs (bottomSizer, wxCentreX);
346 c->centreY.SameAs (bottomSizer, wxCentreY);
347 c->width.PercentOf (bottomSizer, wxWidth, 20);
348 c->height.PercentOf (bottomSizer, wxHeight, 20);
349 button2->SetConstraints(c);
350 }
351
352 BEGIN_EVENT_TABLE(SizerFrame, wxFrame)
353 EVT_SIZE(SizerFrame::OnSize)
354 END_EVENT_TABLE()
355
356
357 // Size the subwindows when the frame is resized
358 void SizerFrame::OnSize(wxSizeEvent& event)
359 {
360 wxFrame::OnSize(event);
361 panel->Layout();
362 }
363
364 //-----------------------------------------------------------------
365 // NewSizerFrame
366 //-----------------------------------------------------------------
367
368 NewSizerFrame::NewSizerFrame(wxFrame *frame, char *title, int x, int y ):
369 wxFrame(frame, -1, title, wxPoint(x, y) )
370 {
371 // we want to get a dialog that is stretchable because it
372 // has a text ctrl in the middle. at the bottom, we have
373 // two buttons which.
374
375 topsizer = new wxBox( wxVERTICAL );
376
377 // 1) top: create wxStaticText with minimum size equal to its default size
378 topsizer->Add(
379 new wxStaticText( this, -1, "An explanation (wxALIGN_RIGHT)." ),
380 0, // make vertically unstretchable
381 wxALIGN_RIGHT | // right align text
382 wxTOP | wxLEFT | wxRIGHT, // make border all around except wxBOTTOM
383 5 ); // set border width to 5
384
385 // 2) top: create wxTextCtrl with minimum size (100x60)
386 topsizer->Add(
387 new wxTextCtrl( this, -1, "My text (wxEXPAND).", wxDefaultPosition, wxSize(100,60), wxTE_MULTILINE),
388 1, // make vertically stretchable
389 wxEXPAND | // make horizontally stretchable
390 wxALL, // and make border all around
391 5 ); // set border width to 5
392
393
394 // 3) middle: create wxStaticLine with minimum size (3x3)
395 topsizer->Add(
396 new wxStaticLine( this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL),
397 0, // make vertically unstretchable
398 wxEXPAND | // make horizontally stretchable
399 wxALL, // and make border all around
400 5 ); // set border width to 5
401
402
403 // 4) bottom: create two centred wxButtons
404 wxBox *button_box = new wxBox( wxHORIZONTAL );
405 button_box->Add(
406 new wxButton( this, -1, "Two buttons in a box" ),
407 0, // make horizontally unstretchable
408 wxALL, // make border all around
409 7 ); // set border width to 7
410 button_box->Add(
411 new wxButton( this, -1, "(wxCENTER)" ),
412 0, // make horizontally unstretchable
413 wxALL, // make border all around
414 7 ); // set border width to 7
415
416 topsizer->Add(
417 button_box,
418 0, // make vertically unstretchable
419 wxCENTER ); // no border and centre horizontally
420
421
422 // set frame to minimum size
423 topsizer->Fit( this );
424
425 // don't allow frame to get smaller than what the sizers tell ye
426 topsizer->SetSizeHints( this );
427
428 // layout widgets
429 topsizer->Layout();
430 }
431
432 // This can later be removed if we integrate wxNewSizers
433 // into wxWindows
434
435 BEGIN_EVENT_TABLE(NewSizerFrame, wxFrame)
436 EVT_SIZE(NewSizerFrame::OnSize)
437 END_EVENT_TABLE()
438
439 void NewSizerFrame::OnSize(wxSizeEvent& event)
440 {
441 wxFrame::OnSize(event);
442
443 wxSize client_size( GetClientSize() );
444
445 topsizer->SetDimension( 0, 0, client_size.x, client_size.y );
446 }
447
448