]> git.saurik.com Git - wxWidgets.git/blob - samples/splitter/splitter.cpp
fix sizing of extra control
[wxWidgets.git] / samples / splitter / splitter.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: splitter.cpp
3 // Purpose: wxSplitterWindow 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 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/log.h"
29
30 #include "wx/app.h"
31 #include "wx/frame.h"
32
33 #include "wx/scrolwin.h"
34 #include "wx/menu.h"
35
36 #include "wx/textdlg.h" // for wxGetTextFromUser
37 #endif
38
39 #include "wx/splitter.h"
40 #include "wx/dcmirror.h"
41
42 // ----------------------------------------------------------------------------
43 // constants
44 // ----------------------------------------------------------------------------
45
46 // ID for the menu commands
47 enum
48 {
49 SPLIT_QUIT = 1,
50 SPLIT_HORIZONTAL,
51 SPLIT_VERTICAL,
52 SPLIT_UNSPLIT,
53 SPLIT_LIVE,
54 SPLIT_BORDER,
55 SPLIT_3DSASH,
56 SPLIT_SETPOSITION,
57 SPLIT_SETMINSIZE,
58 SPLIT_SETGRAVITY,
59 SPLIT_REPLACE
60 };
61
62 // ----------------------------------------------------------------------------
63 // our classes
64 // ----------------------------------------------------------------------------
65
66 class MyApp: public wxApp
67 {
68 public:
69 MyApp() { }
70
71 virtual bool OnInit();
72
73 DECLARE_NO_COPY_CLASS(MyApp)
74 };
75
76 class MyFrame: public wxFrame
77 {
78 public:
79 MyFrame();
80 virtual ~MyFrame();
81
82 // Menu commands
83 void SplitHorizontal(wxCommandEvent& event);
84 void SplitVertical(wxCommandEvent& event);
85 void Unsplit(wxCommandEvent& event);
86 void ToggleFlag(int flag, bool enable);
87 void ToggleLive(wxCommandEvent& event)
88 { ToggleFlag(wxSP_LIVE_UPDATE, event.IsChecked()); }
89 void ToggleBorder(wxCommandEvent& event)
90 { ToggleFlag(wxSP_BORDER, event.IsChecked()); }
91 void Toggle3DSash(wxCommandEvent& event)
92 { ToggleFlag(wxSP_3DSASH, event.IsChecked()); }
93 void SetPosition(wxCommandEvent& event);
94 void SetMinSize(wxCommandEvent& event);
95 void SetGravity(wxCommandEvent& event);
96 void Replace(wxCommandEvent &event);
97
98 void Quit(wxCommandEvent& event);
99
100 // Menu command update functions
101 void UpdateUIHorizontal(wxUpdateUIEvent& event);
102 void UpdateUIVertical(wxUpdateUIEvent& event);
103 void UpdateUIUnsplit(wxUpdateUIEvent& event);
104
105 private:
106 wxScrolledWindow *m_left, *m_right;
107
108 wxSplitterWindow* m_splitter;
109 wxWindow *m_replacewindow;
110
111 DECLARE_EVENT_TABLE()
112 DECLARE_NO_COPY_CLASS(MyFrame)
113 };
114
115 class MySplitterWindow : public wxSplitterWindow
116 {
117 public:
118 MySplitterWindow(wxFrame *parent);
119
120 // event handlers
121 void OnPositionChanged(wxSplitterEvent& event);
122 void OnPositionChanging(wxSplitterEvent& event);
123 void OnDClick(wxSplitterEvent& event);
124 void OnUnsplitEvent(wxSplitterEvent& event);
125
126 private:
127 wxFrame *m_frame;
128
129 DECLARE_EVENT_TABLE()
130 DECLARE_NO_COPY_CLASS(MySplitterWindow)
131 };
132
133 class MyCanvas: public wxScrolledWindow
134 {
135 public:
136 MyCanvas(wxWindow* parent, bool mirror);
137 virtual ~MyCanvas(){};
138
139 virtual void OnDraw(wxDC& dc);
140
141 private:
142 bool m_mirror;
143
144 DECLARE_NO_COPY_CLASS(MyCanvas)
145 };
146
147 // ============================================================================
148 // implementation
149 // ============================================================================
150
151 // ----------------------------------------------------------------------------
152 // MyApp
153 // ----------------------------------------------------------------------------
154
155 IMPLEMENT_APP(MyApp)
156
157 bool MyApp::OnInit()
158 {
159 if ( !wxApp::OnInit() )
160 return false;
161
162 // create and show the main frame
163 MyFrame* frame = new MyFrame;
164
165 frame->Show(true);
166
167 return true;
168 }
169
170 // ----------------------------------------------------------------------------
171 // MyFrame
172 // ----------------------------------------------------------------------------
173
174 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
175 EVT_MENU(SPLIT_VERTICAL, MyFrame::SplitVertical)
176 EVT_MENU(SPLIT_HORIZONTAL, MyFrame::SplitHorizontal)
177 EVT_MENU(SPLIT_UNSPLIT, MyFrame::Unsplit)
178 EVT_MENU(SPLIT_LIVE, MyFrame::ToggleLive)
179 EVT_MENU(SPLIT_BORDER, MyFrame::ToggleBorder)
180 EVT_MENU(SPLIT_3DSASH, MyFrame::Toggle3DSash)
181 EVT_MENU(SPLIT_SETPOSITION, MyFrame::SetPosition)
182 EVT_MENU(SPLIT_SETMINSIZE, MyFrame::SetMinSize)
183 EVT_MENU(SPLIT_SETGRAVITY, MyFrame::SetGravity)
184 EVT_MENU(SPLIT_REPLACE, MyFrame::Replace)
185
186 EVT_MENU(SPLIT_QUIT, MyFrame::Quit)
187
188 EVT_UPDATE_UI(SPLIT_VERTICAL, MyFrame::UpdateUIVertical)
189 EVT_UPDATE_UI(SPLIT_HORIZONTAL, MyFrame::UpdateUIHorizontal)
190 EVT_UPDATE_UI(SPLIT_UNSPLIT, MyFrame::UpdateUIUnsplit)
191 END_EVENT_TABLE()
192
193 // My frame constructor
194 MyFrame::MyFrame()
195 : wxFrame(NULL, wxID_ANY, _T("wxSplitterWindow sample"),
196 wxDefaultPosition, wxSize(420, 300),
197 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
198 {
199 #if wxUSE_STATUSBAR
200 CreateStatusBar(2);
201 #endif // wxUSE_STATUSBAR
202
203 // Make a menubar
204 wxMenu *splitMenu = new wxMenu;
205 splitMenu->Append(SPLIT_VERTICAL,
206 _T("Split &Vertically\tCtrl-V"),
207 _T("Split vertically"));
208 splitMenu->Append(SPLIT_HORIZONTAL,
209 _T("Split &Horizontally\tCtrl-H"),
210 _T("Split horizontally"));
211 splitMenu->Append(SPLIT_UNSPLIT,
212 _T("&Unsplit\tCtrl-U"),
213 _T("Unsplit"));
214 splitMenu->AppendSeparator();
215
216 splitMenu->AppendCheckItem(SPLIT_LIVE,
217 _T("&Live update\tCtrl-L"),
218 _T("Toggle live update mode"));
219 splitMenu->AppendCheckItem(SPLIT_BORDER,
220 _T("3D &Border"),
221 _T("Toggle wxSP_BORDER flag"));
222 splitMenu->Check(SPLIT_BORDER, true);
223 splitMenu->AppendCheckItem(SPLIT_3DSASH,
224 _T("&3D Sash"),
225 _T("Toggle wxSP_3DSASH flag"));
226 splitMenu->Check(SPLIT_3DSASH, true);
227 splitMenu->Append(SPLIT_SETPOSITION,
228 _T("Set splitter &position\tCtrl-P"),
229 _T("Set the splitter position"));
230 splitMenu->Append(SPLIT_SETMINSIZE,
231 _T("Set &min size\tCtrl-M"),
232 _T("Set minimum pane size"));
233 splitMenu->Append(SPLIT_SETGRAVITY,
234 _T("Set &gravity\tCtrl-G"),
235 _T("Set gravity of sash"));
236 splitMenu->AppendSeparator();
237
238 splitMenu->Append(SPLIT_REPLACE,
239 _T("&Replace right window"),
240 _T("Replace right window"));
241 splitMenu->AppendSeparator();
242
243 splitMenu->Append(SPLIT_QUIT, _T("E&xit\tAlt-X"), _T("Exit"));
244
245 wxMenuBar *menuBar = new wxMenuBar;
246 menuBar->Append(splitMenu, _T("&Splitter"));
247
248 SetMenuBar(menuBar);
249
250 menuBar->Check(SPLIT_LIVE, true);
251 m_splitter = new MySplitterWindow(this);
252
253 m_splitter->SetSashGravity(1.0);
254
255 #if 1
256 m_left = new MyCanvas(m_splitter, true);
257 m_left->SetBackgroundColour(*wxRED);
258 m_left->SetScrollbars(20, 20, 5, 5);
259 m_left->SetCursor(wxCursor(wxCURSOR_MAGNIFIER));
260
261 m_right = new MyCanvas(m_splitter, false);
262 m_right->SetBackgroundColour(*wxCYAN);
263 m_right->SetScrollbars(20, 20, 5, 5);
264 #else // for testing kbd navigation inside the splitter
265 m_left = new wxTextCtrl(m_splitter, wxID_ANY, _T("first text"));
266 m_right = new wxTextCtrl(m_splitter, wxID_ANY, _T("second text"));
267 #endif
268
269 // you can also do this to start with a single window
270 #if 0
271 m_right->Show(false);
272 m_splitter->Initialize(m_left);
273 #else
274 // you can also try -100
275 m_splitter->SplitVertically(m_left, m_right, 100);
276 #endif
277
278 #if wxUSE_STATUSBAR
279 SetStatusText(_T("Min pane size = 0"), 1);
280 #endif // wxUSE_STATUSBAR
281
282 m_replacewindow = (wxWindow *)0;
283 }
284
285 MyFrame::~MyFrame()
286 {
287 if (m_replacewindow) {
288 m_replacewindow->Destroy();
289 m_replacewindow = (wxWindow *)0;
290 }
291 }
292
293 // menu command handlers
294
295 void MyFrame::Quit(wxCommandEvent& WXUNUSED(event) )
296 {
297 Close(true);
298 }
299
300 void MyFrame::SplitHorizontal(wxCommandEvent& WXUNUSED(event) )
301 {
302 if ( m_splitter->IsSplit() )
303 m_splitter->Unsplit();
304 m_left->Show(true);
305 m_right->Show(true);
306 m_splitter->SplitHorizontally( m_left, m_right );
307
308 #if wxUSE_STATUSBAR
309 SetStatusText(_T("Splitter split horizontally"), 1);
310 #endif // wxUSE_STATUSBAR
311 }
312
313 void MyFrame::SplitVertical(wxCommandEvent& WXUNUSED(event) )
314 {
315 if ( m_splitter->IsSplit() )
316 m_splitter->Unsplit();
317 m_left->Show(true);
318 m_right->Show(true);
319 m_splitter->SplitVertically( m_left, m_right );
320
321 #if wxUSE_STATUSBAR
322 SetStatusText(_T("Splitter split vertically"), 1);
323 #endif // wxUSE_STATUSBAR
324 }
325
326 void MyFrame::Unsplit(wxCommandEvent& WXUNUSED(event) )
327 {
328 if ( m_splitter->IsSplit() )
329 m_splitter->Unsplit();
330 #if wxUSE_STATUSBAR
331 SetStatusText(_T("No splitter"));
332 #endif // wxUSE_STATUSBAR
333 }
334
335 void MyFrame::ToggleFlag(int flag, bool enable)
336 {
337 long style = m_splitter->GetWindowStyleFlag();
338 if ( enable )
339 style |= flag;
340 else
341 style &= ~flag;
342
343 m_splitter->SetWindowStyleFlag(style);
344
345 // we need to move sash to redraw it
346 int pos = m_splitter->GetSashPosition();
347 m_splitter->SetSashPosition(pos + 1);
348 m_splitter->SetSashPosition(pos);
349 }
350
351 void MyFrame::SetPosition(wxCommandEvent& WXUNUSED(event) )
352 {
353 wxString str;
354 str.Printf( wxT("%d"), m_splitter->GetSashPosition());
355 #if wxUSE_TEXTDLG
356 str = wxGetTextFromUser(_T("Enter splitter position:"), _T(""), str, this);
357 #endif
358 if ( str.empty() )
359 return;
360
361 long pos;
362 if ( !str.ToLong(&pos) )
363 {
364 wxLogError(_T("The splitter position should be an integer."));
365 return;
366 }
367
368 m_splitter->SetSashPosition(pos);
369
370 wxLogStatus(this, _T("Splitter position set to %ld"), pos);
371 }
372
373 void MyFrame::SetMinSize(wxCommandEvent& WXUNUSED(event) )
374 {
375 wxString str;
376 str.Printf( wxT("%d"), m_splitter->GetMinimumPaneSize());
377 #if wxUSE_TEXTDLG
378 str = wxGetTextFromUser(_T("Enter minimal size for panes:"), _T(""), str, this);
379 #endif
380 if ( str.empty() )
381 return;
382
383 int minsize = wxStrtol( str, (wxChar**)NULL, 10 );
384 m_splitter->SetMinimumPaneSize(minsize);
385 #if wxUSE_STATUSBAR
386 str.Printf( wxT("Min pane size = %d"), minsize);
387 SetStatusText(str, 1);
388 #endif // wxUSE_STATUSBAR
389 }
390 void MyFrame::SetGravity(wxCommandEvent& WXUNUSED(event) )
391 {
392 wxString str;
393 str.Printf( wxT("%g"), m_splitter->GetSashGravity());
394 #if wxUSE_TEXTDLG
395 str = wxGetTextFromUser(_T("Enter sash gravity (0,1):"), _T(""), str, this);
396 #endif
397 if ( str.empty() )
398 return;
399
400 double gravity = wxStrtod( str, (wxChar**)NULL);
401 m_splitter->SetSashGravity(gravity);
402 #if wxUSE_STATUSBAR
403 str.Printf( wxT("Gravity = %g"), gravity);
404 SetStatusText(str, 1);
405 #endif // wxUSE_STATUSBAR
406 }
407
408 void MyFrame::Replace(wxCommandEvent& WXUNUSED(event) )
409 {
410 if (m_replacewindow == 0) {
411 m_replacewindow = m_splitter->GetWindow2();
412 m_splitter->ReplaceWindow(m_replacewindow, new wxPanel(m_splitter, wxID_ANY));
413 m_replacewindow->Hide();
414 } else {
415 wxWindow *empty = m_splitter->GetWindow2();
416 m_splitter->ReplaceWindow(empty, m_replacewindow);
417 m_replacewindow->Show();
418 m_replacewindow = 0;
419 empty->Destroy();
420 }
421 }
422
423 // Update UI handlers
424
425 void MyFrame::UpdateUIHorizontal(wxUpdateUIEvent& event)
426 {
427 event.Enable( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_HORIZONTAL) );
428 }
429
430 void MyFrame::UpdateUIVertical(wxUpdateUIEvent& event)
431 {
432 event.Enable( ( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_VERTICAL) ) );
433 }
434
435 void MyFrame::UpdateUIUnsplit(wxUpdateUIEvent& event)
436 {
437 event.Enable( m_splitter->IsSplit() );
438 }
439
440 // ----------------------------------------------------------------------------
441 // MySplitterWindow
442 // ----------------------------------------------------------------------------
443
444 BEGIN_EVENT_TABLE(MySplitterWindow, wxSplitterWindow)
445 EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, MySplitterWindow::OnPositionChanged)
446 EVT_SPLITTER_SASH_POS_CHANGING(wxID_ANY, MySplitterWindow::OnPositionChanging)
447
448 EVT_SPLITTER_DCLICK(wxID_ANY, MySplitterWindow::OnDClick)
449
450 EVT_SPLITTER_UNSPLIT(wxID_ANY, MySplitterWindow::OnUnsplitEvent)
451 END_EVENT_TABLE()
452
453 MySplitterWindow::MySplitterWindow(wxFrame *parent)
454 : wxSplitterWindow(parent, wxID_ANY,
455 wxDefaultPosition, wxDefaultSize,
456 wxSP_3D | wxSP_LIVE_UPDATE |
457 wxCLIP_CHILDREN /* | wxSP_NO_XP_THEME */ )
458 {
459 m_frame = parent;
460 }
461
462 void MySplitterWindow::OnPositionChanged(wxSplitterEvent& event)
463 {
464 wxLogStatus(m_frame, _T("Position has changed, now = %d (or %d)"),
465 event.GetSashPosition(), GetSashPosition());
466
467 event.Skip();
468 }
469
470 void MySplitterWindow::OnPositionChanging(wxSplitterEvent& event)
471 {
472 wxLogStatus(m_frame, _T("Position is changing, now = %d (or %d)"),
473 event.GetSashPosition(), GetSashPosition());
474
475 event.Skip();
476 }
477
478 void MySplitterWindow::OnDClick(wxSplitterEvent& event)
479 {
480 #if wxUSE_STATUSBAR
481 m_frame->SetStatusText(_T("Splitter double clicked"), 1);
482 #endif // wxUSE_STATUSBAR
483
484 event.Skip();
485 }
486
487 void MySplitterWindow::OnUnsplitEvent(wxSplitterEvent& event)
488 {
489 #if wxUSE_STATUSBAR
490 m_frame->SetStatusText(_T("Splitter unsplit"), 1);
491 #endif // wxUSE_STATUSBAR
492
493 event.Skip();
494 }
495
496 // ----------------------------------------------------------------------------
497 // MyCanvas
498 // ----------------------------------------------------------------------------
499
500 MyCanvas::MyCanvas(wxWindow* parent, bool mirror)
501 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
502 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
503 {
504 m_mirror = mirror;
505 }
506
507 void MyCanvas::OnDraw(wxDC& dcOrig)
508 {
509 wxMirrorDC dc(dcOrig, m_mirror);
510
511 dc.SetPen(*wxBLACK_PEN);
512 dc.DrawLine(0, 0, 100, 200);
513
514 dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
515 dc.DrawText(_T("Testing"), 50, 50);
516
517 dc.SetPen(*wxRED_PEN);
518 dc.SetBrush(*wxGREEN_BRUSH);
519 dc.DrawRectangle(120, 120, 100, 80);
520 }
521