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