]> git.saurik.com Git - wxWidgets.git/blame - samples/splitter/splitter.cpp
1945421 applied
[wxWidgets.git] / samples / splitter / splitter.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
6718d773 2// Name: splitter.cpp
c801d85f
KB
3// Purpose: wxSplitterWindow sample
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6aa89a22 8// Copyright: (c) Julian Smart
0d559d69 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
2f294a9c
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f
KB
20// For compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
2f294a9c 24 #pragma hdrstop
c801d85f
KB
25#endif
26
27#ifndef WX_PRECOMP
6faed57d
VZ
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
c801d85f
KB
37#endif
38
39#include "wx/splitter.h"
a63e17c1 40#include "wx/dcmirror.h"
c801d85f 41
2f294a9c
VZ
42// ----------------------------------------------------------------------------
43// constants
44// ----------------------------------------------------------------------------
45
46// ID for the menu commands
47enum
48{
77e0a6d8 49 SPLIT_QUIT = 1,
2f294a9c
VZ
50 SPLIT_HORIZONTAL,
51 SPLIT_VERTICAL,
52 SPLIT_UNSPLIT,
b795f9ca 53 SPLIT_LIVE,
9b8d8755
VZ
54 SPLIT_BORDER,
55 SPLIT_3DSASH,
6faed57d 56 SPLIT_SETPOSITION,
14b4c0ff 57 SPLIT_SETMINSIZE,
8adaf733
JS
58 SPLIT_SETGRAVITY,
59 SPLIT_REPLACE
2f294a9c
VZ
60};
61
62// ----------------------------------------------------------------------------
63// our classes
64// ----------------------------------------------------------------------------
c801d85f
KB
65
66class MyApp: public wxApp
67{
68public:
a63e17c1
VZ
69 MyApp() { }
70
71 virtual bool OnInit();
72
73 DECLARE_NO_COPY_CLASS(MyApp)
c801d85f
KB
74};
75
2f294a9c 76class MyFrame: public wxFrame
c801d85f
KB
77{
78public:
2f294a9c 79 MyFrame();
8adaf733 80 virtual ~MyFrame();
0d559d69 81
2f294a9c
VZ
82 // Menu commands
83 void SplitHorizontal(wxCommandEvent& event);
84 void SplitVertical(wxCommandEvent& event);
85 void Unsplit(wxCommandEvent& event);
9b8d8755
VZ
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()); }
6faed57d 93 void SetPosition(wxCommandEvent& event);
2f294a9c 94 void SetMinSize(wxCommandEvent& event);
14b4c0ff 95 void SetGravity(wxCommandEvent& event);
8adaf733 96 void Replace(wxCommandEvent &event);
b795f9ca 97
2f294a9c 98 void Quit(wxCommandEvent& event);
4a0b46a7 99
2f294a9c
VZ
100 // Menu command update functions
101 void UpdateUIHorizontal(wxUpdateUIEvent& event);
102 void UpdateUIVertical(wxUpdateUIEvent& event);
103 void UpdateUIUnsplit(wxUpdateUIEvent& event);
4a0b46a7 104
0d559d69 105private:
2f294a9c
VZ
106 wxScrolledWindow *m_left, *m_right;
107
108 wxSplitterWindow* m_splitter;
8adaf733 109 wxWindow *m_replacewindow;
2f294a9c
VZ
110
111 DECLARE_EVENT_TABLE()
a63e17c1 112 DECLARE_NO_COPY_CLASS(MyFrame)
0d559d69 113};
c801d85f 114
2f294a9c 115class MySplitterWindow : public wxSplitterWindow
0d559d69
VZ
116{
117public:
2f294a9c 118 MySplitterWindow(wxFrame *parent);
c801d85f 119
2f294a9c
VZ
120 // event handlers
121 void OnPositionChanged(wxSplitterEvent& event);
122 void OnPositionChanging(wxSplitterEvent& event);
123 void OnDClick(wxSplitterEvent& event);
8ad18dc3 124 void OnUnsplitEvent(wxSplitterEvent& event);
c801d85f
KB
125
126private:
2f294a9c 127 wxFrame *m_frame;
0d559d69 128
2f294a9c 129 DECLARE_EVENT_TABLE()
a63e17c1 130 DECLARE_NO_COPY_CLASS(MySplitterWindow)
c801d85f
KB
131};
132
133class MyCanvas: public wxScrolledWindow
134{
135public:
a63e17c1 136 MyCanvas(wxWindow* parent, bool mirror);
925e9792 137 virtual ~MyCanvas(){};
c801d85f 138
2f294a9c 139 virtual void OnDraw(wxDC& dc);
a63e17c1
VZ
140
141private:
142 bool m_mirror;
143
144 DECLARE_NO_COPY_CLASS(MyCanvas)
c801d85f
KB
145};
146
2f294a9c
VZ
147// ============================================================================
148// implementation
149// ============================================================================
c801d85f 150
2f294a9c
VZ
151// ----------------------------------------------------------------------------
152// MyApp
153// ----------------------------------------------------------------------------
0d57be45 154
c801d85f
KB
155IMPLEMENT_APP(MyApp)
156
2f294a9c 157bool MyApp::OnInit()
c801d85f 158{
45e6e6f8
VZ
159 if ( !wxApp::OnInit() )
160 return false;
161
2f294a9c
VZ
162 // create and show the main frame
163 MyFrame* frame = new MyFrame;
4a0b46a7 164
8ad18dc3 165 frame->Show(true);
c801d85f 166
8ad18dc3 167 return true;
c801d85f
KB
168}
169
2f294a9c
VZ
170// ----------------------------------------------------------------------------
171// MyFrame
172// ----------------------------------------------------------------------------
173
c801d85f 174BEGIN_EVENT_TABLE(MyFrame, wxFrame)
2f294a9c
VZ
175 EVT_MENU(SPLIT_VERTICAL, MyFrame::SplitVertical)
176 EVT_MENU(SPLIT_HORIZONTAL, MyFrame::SplitHorizontal)
177 EVT_MENU(SPLIT_UNSPLIT, MyFrame::Unsplit)
b795f9ca 178 EVT_MENU(SPLIT_LIVE, MyFrame::ToggleLive)
9b8d8755
VZ
179 EVT_MENU(SPLIT_BORDER, MyFrame::ToggleBorder)
180 EVT_MENU(SPLIT_3DSASH, MyFrame::Toggle3DSash)
6faed57d 181 EVT_MENU(SPLIT_SETPOSITION, MyFrame::SetPosition)
2f294a9c 182 EVT_MENU(SPLIT_SETMINSIZE, MyFrame::SetMinSize)
14b4c0ff 183 EVT_MENU(SPLIT_SETGRAVITY, MyFrame::SetGravity)
8adaf733 184 EVT_MENU(SPLIT_REPLACE, MyFrame::Replace)
2f294a9c 185
b795f9ca
VZ
186 EVT_MENU(SPLIT_QUIT, MyFrame::Quit)
187
2f294a9c
VZ
188 EVT_UPDATE_UI(SPLIT_VERTICAL, MyFrame::UpdateUIVertical)
189 EVT_UPDATE_UI(SPLIT_HORIZONTAL, MyFrame::UpdateUIHorizontal)
190 EVT_UPDATE_UI(SPLIT_UNSPLIT, MyFrame::UpdateUIUnsplit)
c801d85f
KB
191END_EVENT_TABLE()
192
193// My frame constructor
2f294a9c 194MyFrame::MyFrame()
8ad18dc3 195 : wxFrame(NULL, wxID_ANY, _T("wxSplitterWindow sample"),
2f294a9c 196 wxDefaultPosition, wxSize(420, 300),
fe31f91c 197 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
c801d85f 198{
8520f137 199#if wxUSE_STATUSBAR
2f294a9c 200 CreateStatusBar(2);
8520f137 201#endif // wxUSE_STATUSBAR
b7346a70 202
2f294a9c 203 // Make a menubar
6faed57d
VZ
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"));
9b8d8755
VZ
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);
6faed57d
VZ
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"));
14b4c0ff
VZ
233 splitMenu->Append(SPLIT_SETGRAVITY,
234 _T("Set &gravity\tCtrl-G"),
235 _T("Set gravity of sash"));
6faed57d
VZ
236 splitMenu->AppendSeparator();
237
8adaf733
JS
238 splitMenu->Append(SPLIT_REPLACE,
239 _T("&Replace right window"),
240 _T("Replace right window"));
241 splitMenu->AppendSeparator();
242
6faed57d 243 splitMenu->Append(SPLIT_QUIT, _T("E&xit\tAlt-X"), _T("Exit"));
c801d85f 244
2f294a9c 245 wxMenuBar *menuBar = new wxMenuBar;
6faed57d 246 menuBar->Append(splitMenu, _T("&Splitter"));
c801d85f 247
2f294a9c 248 SetMenuBar(menuBar);
c801d85f 249
8ad18dc3 250 menuBar->Check(SPLIT_LIVE, true);
2f294a9c 251 m_splitter = new MySplitterWindow(this);
14b4c0ff
VZ
252
253 m_splitter->SetSashGravity(1.0);
4a0b46a7 254
6b55490a 255#if 1
a63e17c1 256 m_left = new MyCanvas(m_splitter, true);
2f294a9c 257 m_left->SetBackgroundColour(*wxRED);
a63e17c1 258 m_left->SetScrollbars(20, 20, 5, 5);
2f294a9c
VZ
259 m_left->SetCursor(wxCursor(wxCURSOR_MAGNIFIER));
260
a63e17c1 261 m_right = new MyCanvas(m_splitter, false);
2f294a9c 262 m_right->SetBackgroundColour(*wxCYAN);
a63e17c1 263 m_right->SetScrollbars(20, 20, 5, 5);
6b55490a 264#else // for testing kbd navigation inside the splitter
8ad18dc3
JS
265 m_left = new wxTextCtrl(m_splitter, wxID_ANY, _T("first text"));
266 m_right = new wxTextCtrl(m_splitter, wxID_ANY, _T("second text"));
6b55490a 267#endif
c801d85f 268
2f294a9c 269 // you can also do this to start with a single window
4a0b46a7 270#if 0
8ad18dc3 271 m_right->Show(false);
2f294a9c 272 m_splitter->Initialize(m_left);
4a0b46a7 273#else
74c57d1f 274 // you can also try -100
2f294a9c 275 m_splitter->SplitVertically(m_left, m_right, 100);
4a0b46a7
VZ
276#endif
277
8520f137 278#if wxUSE_STATUSBAR
2f294a9c 279 SetStatusText(_T("Min pane size = 0"), 1);
8520f137 280#endif // wxUSE_STATUSBAR
8adaf733
JS
281
282 m_replacewindow = (wxWindow *)0;
283}
284
285MyFrame::~MyFrame()
286{
287 if (m_replacewindow) {
288 m_replacewindow->Destroy();
289 m_replacewindow = (wxWindow *)0;
290 }
c801d85f
KB
291}
292
2f294a9c
VZ
293// menu command handlers
294
e3e65dac 295void MyFrame::Quit(wxCommandEvent& WXUNUSED(event) )
c801d85f 296{
8ad18dc3 297 Close(true);
c801d85f
KB
298}
299
e3e65dac 300void MyFrame::SplitHorizontal(wxCommandEvent& WXUNUSED(event) )
c801d85f 301{
2f294a9c
VZ
302 if ( m_splitter->IsSplit() )
303 m_splitter->Unsplit();
8ad18dc3
JS
304 m_left->Show(true);
305 m_right->Show(true);
2f294a9c 306 m_splitter->SplitHorizontally( m_left, m_right );
74c57d1f 307
8520f137 308#if wxUSE_STATUSBAR
74c57d1f 309 SetStatusText(_T("Splitter split horizontally"), 1);
8520f137 310#endif // wxUSE_STATUSBAR
c801d85f
KB
311}
312
e3e65dac 313void MyFrame::SplitVertical(wxCommandEvent& WXUNUSED(event) )
c801d85f 314{
2f294a9c
VZ
315 if ( m_splitter->IsSplit() )
316 m_splitter->Unsplit();
8ad18dc3
JS
317 m_left->Show(true);
318 m_right->Show(true);
2f294a9c 319 m_splitter->SplitVertically( m_left, m_right );
74c57d1f 320
8520f137 321#if wxUSE_STATUSBAR
74c57d1f 322 SetStatusText(_T("Splitter split vertically"), 1);
8520f137 323#endif // wxUSE_STATUSBAR
c801d85f
KB
324}
325
e3e65dac 326void MyFrame::Unsplit(wxCommandEvent& WXUNUSED(event) )
c801d85f 327{
2f294a9c
VZ
328 if ( m_splitter->IsSplit() )
329 m_splitter->Unsplit();
8520f137 330#if wxUSE_STATUSBAR
2f294a9c 331 SetStatusText(_T("No splitter"));
8520f137 332#endif // wxUSE_STATUSBAR
0d559d69
VZ
333}
334
9b8d8755 335void MyFrame::ToggleFlag(int flag, bool enable)
b795f9ca
VZ
336{
337 long style = m_splitter->GetWindowStyleFlag();
9b8d8755
VZ
338 if ( enable )
339 style |= flag;
b795f9ca 340 else
9b8d8755 341 style &= ~flag;
b795f9ca
VZ
342
343 m_splitter->SetWindowStyleFlag(style);
9b8d8755
VZ
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);
b795f9ca
VZ
349}
350
6faed57d
VZ
351void MyFrame::SetPosition(wxCommandEvent& WXUNUSED(event) )
352{
353 wxString str;
354 str.Printf( wxT("%d"), m_splitter->GetSashPosition());
9b8d8755 355#if wxUSE_TEXTDLG
6faed57d 356 str = wxGetTextFromUser(_T("Enter splitter position:"), _T(""), str, this);
9b8d8755 357#endif
6faed57d
VZ
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
0d559d69
VZ
373void MyFrame::SetMinSize(wxCommandEvent& WXUNUSED(event) )
374{
2f294a9c 375 wxString str;
f565a6c2 376 str.Printf( wxT("%d"), m_splitter->GetMinimumPaneSize());
9b8d8755 377#if wxUSE_TEXTDLG
2f294a9c 378 str = wxGetTextFromUser(_T("Enter minimal size for panes:"), _T(""), str, this);
9b8d8755 379#endif
6faed57d 380 if ( str.empty() )
2f294a9c
VZ
381 return;
382
383 int minsize = wxStrtol( str, (wxChar**)NULL, 10 );
384 m_splitter->SetMinimumPaneSize(minsize);
8520f137 385#if wxUSE_STATUSBAR
f565a6c2 386 str.Printf( wxT("Min pane size = %d"), minsize);
2f294a9c 387 SetStatusText(str, 1);
8520f137 388#endif // wxUSE_STATUSBAR
c801d85f 389}
14b4c0ff
VZ
390void MyFrame::SetGravity(wxCommandEvent& WXUNUSED(event) )
391{
392 wxString str;
393 str.Printf( wxT("%g"), m_splitter->GetSashGravity());
9b8d8755 394#if wxUSE_TEXTDLG
14b4c0ff 395 str = wxGetTextFromUser(_T("Enter sash gravity (0,1):"), _T(""), str, this);
9b8d8755 396#endif
14b4c0ff
VZ
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}
c801d85f 407
8adaf733
JS
408void 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
2f294a9c
VZ
423// Update UI handlers
424
c801d85f
KB
425void MyFrame::UpdateUIHorizontal(wxUpdateUIEvent& event)
426{
2f294a9c 427 event.Enable( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_HORIZONTAL) );
c801d85f
KB
428}
429
430void MyFrame::UpdateUIVertical(wxUpdateUIEvent& event)
431{
2f294a9c 432 event.Enable( ( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_VERTICAL) ) );
c801d85f
KB
433}
434
435void MyFrame::UpdateUIUnsplit(wxUpdateUIEvent& event)
436{
2f294a9c 437 event.Enable( m_splitter->IsSplit() );
c801d85f
KB
438}
439
2f294a9c
VZ
440// ----------------------------------------------------------------------------
441// MySplitterWindow
442// ----------------------------------------------------------------------------
443
444BEGIN_EVENT_TABLE(MySplitterWindow, wxSplitterWindow)
8ad18dc3
JS
445 EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, MySplitterWindow::OnPositionChanged)
446 EVT_SPLITTER_SASH_POS_CHANGING(wxID_ANY, MySplitterWindow::OnPositionChanging)
2f294a9c 447
8ad18dc3 448 EVT_SPLITTER_DCLICK(wxID_ANY, MySplitterWindow::OnDClick)
2f294a9c 449
8ad18dc3 450 EVT_SPLITTER_UNSPLIT(wxID_ANY, MySplitterWindow::OnUnsplitEvent)
2f294a9c
VZ
451END_EVENT_TABLE()
452
453MySplitterWindow::MySplitterWindow(wxFrame *parent)
8ad18dc3 454 : wxSplitterWindow(parent, wxID_ANY,
2f294a9c 455 wxDefaultPosition, wxDefaultSize,
3c2544bb
JS
456 wxSP_3D | wxSP_LIVE_UPDATE |
457 wxCLIP_CHILDREN /* | wxSP_NO_XP_THEME */ )
c801d85f 458{
2f294a9c 459 m_frame = parent;
c801d85f
KB
460}
461
2f294a9c
VZ
462void 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
470void 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
478void MySplitterWindow::OnDClick(wxSplitterEvent& event)
479{
8520f137 480#if wxUSE_STATUSBAR
2f294a9c 481 m_frame->SetStatusText(_T("Splitter double clicked"), 1);
8520f137 482#endif // wxUSE_STATUSBAR
2f294a9c
VZ
483
484 event.Skip();
485}
486
8ad18dc3 487void MySplitterWindow::OnUnsplitEvent(wxSplitterEvent& event)
2f294a9c 488{
8520f137 489#if wxUSE_STATUSBAR
2f294a9c 490 m_frame->SetStatusText(_T("Splitter unsplit"), 1);
8520f137 491#endif // wxUSE_STATUSBAR
2f294a9c
VZ
492
493 event.Skip();
494}
495
496// ----------------------------------------------------------------------------
497// MyCanvas
498// ----------------------------------------------------------------------------
499
a63e17c1 500MyCanvas::MyCanvas(wxWindow* parent, bool mirror)
8ad18dc3 501 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
a63e17c1 502 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
c801d85f 503{
a63e17c1 504 m_mirror = mirror;
c801d85f
KB
505}
506
a63e17c1 507void MyCanvas::OnDraw(wxDC& dcOrig)
c801d85f 508{
a63e17c1
VZ
509 wxMirrorDC dc(dcOrig, m_mirror);
510
2f294a9c 511 dc.SetPen(*wxBLACK_PEN);
a63e17c1 512 dc.DrawLine(0, 0, 100, 200);
c801d85f 513
9b8d8755 514 dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
2f294a9c 515 dc.DrawText(_T("Testing"), 50, 50);
b7346a70 516
2f294a9c
VZ
517 dc.SetPen(*wxRED_PEN);
518 dc.SetBrush(*wxGREEN_BRUSH);
519 dc.DrawRectangle(120, 120, 100, 80);
c801d85f 520}
2f294a9c 521