]> git.saurik.com Git - wxWidgets.git/blame - samples/splitter/splitter.cpp
document the wxWindow::Get/SetLayoutDirection functions
[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
9b8d8755 82 void ToggleFlag(int flag, bool enable);
430bdeb5
FM
83
84 // Menu commands
85 void OnSplitHorizontal(wxCommandEvent& event);
86 void OnSplitVertical(wxCommandEvent& event);
87 void OnUnsplit(wxCommandEvent& event);
88 void OnToggleLive(wxCommandEvent& event)
9b8d8755 89 { ToggleFlag(wxSP_LIVE_UPDATE, event.IsChecked()); }
430bdeb5 90 void OnToggleBorder(wxCommandEvent& event)
9b8d8755 91 { ToggleFlag(wxSP_BORDER, event.IsChecked()); }
430bdeb5 92 void OnToggle3DSash(wxCommandEvent& event)
9b8d8755 93 { ToggleFlag(wxSP_3DSASH, event.IsChecked()); }
430bdeb5
FM
94 void OnSetPosition(wxCommandEvent& event);
95 void OnSetMinSize(wxCommandEvent& event);
96 void OnSetGravity(wxCommandEvent& event);
97 void OnReplace(wxCommandEvent &event);
b795f9ca 98
430bdeb5 99 void OnQuit(wxCommandEvent& event);
4a0b46a7 100
2f294a9c 101 // Menu command update functions
430bdeb5
FM
102 void OnUpdateUIHorizontal(wxUpdateUIEvent& event);
103 void OnUpdateUIVertical(wxUpdateUIEvent& event);
104 void OnUpdateUIUnsplit(wxUpdateUIEvent& event);
4a0b46a7 105
0d559d69 106private:
2f294a9c
VZ
107 wxScrolledWindow *m_left, *m_right;
108
109 wxSplitterWindow* m_splitter;
8adaf733 110 wxWindow *m_replacewindow;
2f294a9c
VZ
111
112 DECLARE_EVENT_TABLE()
a63e17c1 113 DECLARE_NO_COPY_CLASS(MyFrame)
0d559d69 114};
c801d85f 115
2f294a9c 116class MySplitterWindow : public wxSplitterWindow
0d559d69
VZ
117{
118public:
2f294a9c 119 MySplitterWindow(wxFrame *parent);
c801d85f 120
2f294a9c
VZ
121 // event handlers
122 void OnPositionChanged(wxSplitterEvent& event);
123 void OnPositionChanging(wxSplitterEvent& event);
124 void OnDClick(wxSplitterEvent& event);
8ad18dc3 125 void OnUnsplitEvent(wxSplitterEvent& event);
c801d85f
KB
126
127private:
2f294a9c 128 wxFrame *m_frame;
0d559d69 129
2f294a9c 130 DECLARE_EVENT_TABLE()
a63e17c1 131 DECLARE_NO_COPY_CLASS(MySplitterWindow)
c801d85f
KB
132};
133
134class MyCanvas: public wxScrolledWindow
135{
136public:
a63e17c1 137 MyCanvas(wxWindow* parent, bool mirror);
925e9792 138 virtual ~MyCanvas(){};
c801d85f 139
2f294a9c 140 virtual void OnDraw(wxDC& dc);
a63e17c1
VZ
141
142private:
143 bool m_mirror;
144
145 DECLARE_NO_COPY_CLASS(MyCanvas)
c801d85f
KB
146};
147
2f294a9c
VZ
148// ============================================================================
149// implementation
150// ============================================================================
c801d85f 151
2f294a9c
VZ
152// ----------------------------------------------------------------------------
153// MyApp
154// ----------------------------------------------------------------------------
0d57be45 155
c801d85f
KB
156IMPLEMENT_APP(MyApp)
157
2f294a9c 158bool MyApp::OnInit()
c801d85f 159{
45e6e6f8
VZ
160 if ( !wxApp::OnInit() )
161 return false;
162
2f294a9c
VZ
163 // create and show the main frame
164 MyFrame* frame = new MyFrame;
4a0b46a7 165
8ad18dc3 166 frame->Show(true);
c801d85f 167
8ad18dc3 168 return true;
c801d85f
KB
169}
170
2f294a9c
VZ
171// ----------------------------------------------------------------------------
172// MyFrame
173// ----------------------------------------------------------------------------
174
c801d85f 175BEGIN_EVENT_TABLE(MyFrame, wxFrame)
430bdeb5
FM
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)
c801d85f
KB
192END_EVENT_TABLE()
193
194// My frame constructor
2f294a9c 195MyFrame::MyFrame()
8ad18dc3 196 : wxFrame(NULL, wxID_ANY, _T("wxSplitterWindow sample"),
2f294a9c 197 wxDefaultPosition, wxSize(420, 300),
fe31f91c 198 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
c801d85f 199{
8520f137 200#if wxUSE_STATUSBAR
2f294a9c 201 CreateStatusBar(2);
8520f137 202#endif // wxUSE_STATUSBAR
b7346a70 203
2f294a9c 204 // Make a menubar
6faed57d
VZ
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"));
9b8d8755
VZ
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);
6faed57d
VZ
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"));
14b4c0ff
VZ
234 splitMenu->Append(SPLIT_SETGRAVITY,
235 _T("Set &gravity\tCtrl-G"),
236 _T("Set gravity of sash"));
6faed57d
VZ
237 splitMenu->AppendSeparator();
238
8adaf733
JS
239 splitMenu->Append(SPLIT_REPLACE,
240 _T("&Replace right window"),
241 _T("Replace right window"));
242 splitMenu->AppendSeparator();
243
6faed57d 244 splitMenu->Append(SPLIT_QUIT, _T("E&xit\tAlt-X"), _T("Exit"));
c801d85f 245
2f294a9c 246 wxMenuBar *menuBar = new wxMenuBar;
6faed57d 247 menuBar->Append(splitMenu, _T("&Splitter"));
c801d85f 248
2f294a9c 249 SetMenuBar(menuBar);
c801d85f 250
8ad18dc3 251 menuBar->Check(SPLIT_LIVE, true);
2f294a9c 252 m_splitter = new MySplitterWindow(this);
430bdeb5 253
14b4c0ff 254 m_splitter->SetSashGravity(1.0);
4a0b46a7 255
6b55490a 256#if 1
a63e17c1 257 m_left = new MyCanvas(m_splitter, true);
2f294a9c 258 m_left->SetBackgroundColour(*wxRED);
a63e17c1 259 m_left->SetScrollbars(20, 20, 5, 5);
2f294a9c
VZ
260 m_left->SetCursor(wxCursor(wxCURSOR_MAGNIFIER));
261
a63e17c1 262 m_right = new MyCanvas(m_splitter, false);
2f294a9c 263 m_right->SetBackgroundColour(*wxCYAN);
a63e17c1 264 m_right->SetScrollbars(20, 20, 5, 5);
6b55490a 265#else // for testing kbd navigation inside the splitter
8ad18dc3
JS
266 m_left = new wxTextCtrl(m_splitter, wxID_ANY, _T("first text"));
267 m_right = new wxTextCtrl(m_splitter, wxID_ANY, _T("second text"));
6b55490a 268#endif
c801d85f 269
2f294a9c 270 // you can also do this to start with a single window
4a0b46a7 271#if 0
8ad18dc3 272 m_right->Show(false);
2f294a9c 273 m_splitter->Initialize(m_left);
4a0b46a7 274#else
74c57d1f 275 // you can also try -100
2f294a9c 276 m_splitter->SplitVertically(m_left, m_right, 100);
4a0b46a7
VZ
277#endif
278
8520f137 279#if wxUSE_STATUSBAR
2f294a9c 280 SetStatusText(_T("Min pane size = 0"), 1);
8520f137 281#endif // wxUSE_STATUSBAR
8adaf733
JS
282
283 m_replacewindow = (wxWindow *)0;
284}
285
286MyFrame::~MyFrame()
287{
288 if (m_replacewindow) {
289 m_replacewindow->Destroy();
290 m_replacewindow = (wxWindow *)0;
291 }
c801d85f
KB
292}
293
2f294a9c
VZ
294// menu command handlers
295
430bdeb5 296void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
c801d85f 297{
8ad18dc3 298 Close(true);
c801d85f
KB
299}
300
430bdeb5 301void MyFrame::OnSplitHorizontal(wxCommandEvent& WXUNUSED(event) )
c801d85f 302{
2f294a9c
VZ
303 if ( m_splitter->IsSplit() )
304 m_splitter->Unsplit();
8ad18dc3
JS
305 m_left->Show(true);
306 m_right->Show(true);
2f294a9c 307 m_splitter->SplitHorizontally( m_left, m_right );
74c57d1f 308
8520f137 309#if wxUSE_STATUSBAR
74c57d1f 310 SetStatusText(_T("Splitter split horizontally"), 1);
8520f137 311#endif // wxUSE_STATUSBAR
c801d85f
KB
312}
313
430bdeb5 314void MyFrame::OnSplitVertical(wxCommandEvent& WXUNUSED(event) )
c801d85f 315{
2f294a9c
VZ
316 if ( m_splitter->IsSplit() )
317 m_splitter->Unsplit();
8ad18dc3
JS
318 m_left->Show(true);
319 m_right->Show(true);
2f294a9c 320 m_splitter->SplitVertically( m_left, m_right );
74c57d1f 321
8520f137 322#if wxUSE_STATUSBAR
74c57d1f 323 SetStatusText(_T("Splitter split vertically"), 1);
8520f137 324#endif // wxUSE_STATUSBAR
c801d85f
KB
325}
326
430bdeb5 327void MyFrame::OnUnsplit(wxCommandEvent& WXUNUSED(event) )
c801d85f 328{
2f294a9c
VZ
329 if ( m_splitter->IsSplit() )
330 m_splitter->Unsplit();
8520f137 331#if wxUSE_STATUSBAR
2f294a9c 332 SetStatusText(_T("No splitter"));
8520f137 333#endif // wxUSE_STATUSBAR
0d559d69
VZ
334}
335
9b8d8755 336void MyFrame::ToggleFlag(int flag, bool enable)
b795f9ca
VZ
337{
338 long style = m_splitter->GetWindowStyleFlag();
9b8d8755
VZ
339 if ( enable )
340 style |= flag;
b795f9ca 341 else
9b8d8755 342 style &= ~flag;
b795f9ca
VZ
343
344 m_splitter->SetWindowStyleFlag(style);
9b8d8755
VZ
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);
b795f9ca
VZ
350}
351
430bdeb5 352void MyFrame::OnSetPosition(wxCommandEvent& WXUNUSED(event) )
6faed57d
VZ
353{
354 wxString str;
355 str.Printf( wxT("%d"), m_splitter->GetSashPosition());
9b8d8755 356#if wxUSE_TEXTDLG
6faed57d 357 str = wxGetTextFromUser(_T("Enter splitter position:"), _T(""), str, this);
9b8d8755 358#endif
6faed57d
VZ
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
430bdeb5 374void MyFrame::OnSetMinSize(wxCommandEvent& WXUNUSED(event) )
0d559d69 375{
2f294a9c 376 wxString str;
f565a6c2 377 str.Printf( wxT("%d"), m_splitter->GetMinimumPaneSize());
9b8d8755 378#if wxUSE_TEXTDLG
2f294a9c 379 str = wxGetTextFromUser(_T("Enter minimal size for panes:"), _T(""), str, this);
9b8d8755 380#endif
6faed57d 381 if ( str.empty() )
2f294a9c
VZ
382 return;
383
384 int minsize = wxStrtol( str, (wxChar**)NULL, 10 );
385 m_splitter->SetMinimumPaneSize(minsize);
8520f137 386#if wxUSE_STATUSBAR
f565a6c2 387 str.Printf( wxT("Min pane size = %d"), minsize);
2f294a9c 388 SetStatusText(str, 1);
8520f137 389#endif // wxUSE_STATUSBAR
c801d85f 390}
430bdeb5
FM
391
392void MyFrame::OnSetGravity(wxCommandEvent& WXUNUSED(event) )
14b4c0ff
VZ
393{
394 wxString str;
395 str.Printf( wxT("%g"), m_splitter->GetSashGravity());
9b8d8755 396#if wxUSE_TEXTDLG
14b4c0ff 397 str = wxGetTextFromUser(_T("Enter sash gravity (0,1):"), _T(""), str, this);
9b8d8755 398#endif
14b4c0ff
VZ
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}
c801d85f 409
430bdeb5 410void MyFrame::OnReplace(wxCommandEvent& WXUNUSED(event) )
8adaf733
JS
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
2f294a9c
VZ
425// Update UI handlers
426
430bdeb5 427void MyFrame::OnUpdateUIHorizontal(wxUpdateUIEvent& event)
c801d85f 428{
2f294a9c 429 event.Enable( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_HORIZONTAL) );
c801d85f
KB
430}
431
430bdeb5 432void MyFrame::OnUpdateUIVertical(wxUpdateUIEvent& event)
c801d85f 433{
2f294a9c 434 event.Enable( ( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_VERTICAL) ) );
c801d85f
KB
435}
436
430bdeb5 437void MyFrame::OnUpdateUIUnsplit(wxUpdateUIEvent& event)
c801d85f 438{
2f294a9c 439 event.Enable( m_splitter->IsSplit() );
c801d85f
KB
440}
441
2f294a9c
VZ
442// ----------------------------------------------------------------------------
443// MySplitterWindow
444// ----------------------------------------------------------------------------
445
446BEGIN_EVENT_TABLE(MySplitterWindow, wxSplitterWindow)
8ad18dc3
JS
447 EVT_SPLITTER_SASH_POS_CHANGED(wxID_ANY, MySplitterWindow::OnPositionChanged)
448 EVT_SPLITTER_SASH_POS_CHANGING(wxID_ANY, MySplitterWindow::OnPositionChanging)
2f294a9c 449
8ad18dc3 450 EVT_SPLITTER_DCLICK(wxID_ANY, MySplitterWindow::OnDClick)
2f294a9c 451
8ad18dc3 452 EVT_SPLITTER_UNSPLIT(wxID_ANY, MySplitterWindow::OnUnsplitEvent)
2f294a9c
VZ
453END_EVENT_TABLE()
454
455MySplitterWindow::MySplitterWindow(wxFrame *parent)
8ad18dc3 456 : wxSplitterWindow(parent, wxID_ANY,
2f294a9c 457 wxDefaultPosition, wxDefaultSize,
3c2544bb
JS
458 wxSP_3D | wxSP_LIVE_UPDATE |
459 wxCLIP_CHILDREN /* | wxSP_NO_XP_THEME */ )
c801d85f 460{
2f294a9c 461 m_frame = parent;
c801d85f
KB
462}
463
2f294a9c
VZ
464void 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
472void 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
480void MySplitterWindow::OnDClick(wxSplitterEvent& event)
481{
8520f137 482#if wxUSE_STATUSBAR
2f294a9c 483 m_frame->SetStatusText(_T("Splitter double clicked"), 1);
8520f137 484#endif // wxUSE_STATUSBAR
2f294a9c
VZ
485
486 event.Skip();
487}
488
8ad18dc3 489void MySplitterWindow::OnUnsplitEvent(wxSplitterEvent& event)
2f294a9c 490{
8520f137 491#if wxUSE_STATUSBAR
2f294a9c 492 m_frame->SetStatusText(_T("Splitter unsplit"), 1);
8520f137 493#endif // wxUSE_STATUSBAR
2f294a9c
VZ
494
495 event.Skip();
496}
497
498// ----------------------------------------------------------------------------
499// MyCanvas
500// ----------------------------------------------------------------------------
501
a63e17c1 502MyCanvas::MyCanvas(wxWindow* parent, bool mirror)
8ad18dc3 503 : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
a63e17c1 504 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
c801d85f 505{
a63e17c1 506 m_mirror = mirror;
c801d85f
KB
507}
508
a63e17c1 509void MyCanvas::OnDraw(wxDC& dcOrig)
c801d85f 510{
a63e17c1
VZ
511 wxMirrorDC dc(dcOrig, m_mirror);
512
2f294a9c 513 dc.SetPen(*wxBLACK_PEN);
a63e17c1 514 dc.DrawLine(0, 0, 100, 200);
c801d85f 515
9b8d8755 516 dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
2f294a9c 517 dc.DrawText(_T("Testing"), 50, 50);
b7346a70 518
2f294a9c
VZ
519 dc.SetPen(*wxRED_PEN);
520 dc.SetBrush(*wxGREEN_BRUSH);
521 dc.DrawRectangle(120, 120, 100, 80);
c801d85f 522}
2f294a9c 523