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