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