From 0d559d69c8115c8aaabba70f37d49b4effbc2ab2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 23 Oct 1998 13:15:15 +0000 Subject: [PATCH] 1. Split{Horizontal|Vertical} now accept negative args to set the size of right/lower pane (positive arg sets the size of left/upper one as before, 0 is the same as -1 before: choose default) 2. OnSashPositionChange() virtual function added - it may return FALSE to cancel position change 3. splitter sample and docs (couldn't compile them though) updated git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@901 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/splitter.tex | 39 ++++-- include/wx/generic/splitter.h | 71 ++++++---- samples/splitter/test.cpp | 240 ++++++++++++++++++++-------------- src/generic/splitter.cpp | 163 +++++++++++++---------- 4 files changed, 305 insertions(+), 208 deletions(-) diff --git a/docs/latex/wx/splitter.tex b/docs/latex/wx/splitter.tex index 9febf0b911..f2631badff 100644 --- a/docs/latex/wx/splitter.tex +++ b/docs/latex/wx/splitter.tex @@ -189,9 +189,25 @@ programmatically or using the wxSplitterWindow user interface. The default implementation of this function simply hides {\it removed}. You may wish to delete the window. +\membersection{wxSplitterWindow::OnSashPositionChange}\label{wxsplitterwindowonsashpositionchange} + +\func{virtual bool}{OnSashPositionChange}{\param{int }{newSashPosition} + +Application-overridable function called when the sash position is changed by +user. It may return FALSE to prevent the change or TRUE to allow it. + +\wxheading{Parameters} + +\docparam{newSashPosition}{The new sash position (always positive or zero)} + +\wxheading{Remarks} + +The default implementation of this function verifies that the sizes of both +panes of the splitter are greater than minimum pane size. + \wxheading{See also} -\helpref{wxSplitterWindow::Unsplit}{wxsplitterwindowunsplit} +\helpref{wxSplitterWindow::GetMinimumPaneSize}{wxsplitterwindowgetminimumpanesize} \membersection{wxSplitterWindow::SetSashPosition}\label{wxsplitterwindowsetsashposition} @@ -255,7 +271,7 @@ Only sets the internal variable; does not update the display. \membersection{wxSplitterWindow::SplitHorizontally}\label{wxsplitterwindowsplithorizontally} \func{bool}{SplitHorizontally}{\param{wxWindow* }{window1}, \param{wxWindow* }{window2}, - \param{int}{ sashPosition = -1}} + \param{int}{ sashPosition = 0}} Initializes the top and bottom panes of the splitter window. @@ -265,8 +281,10 @@ Initializes the top and bottom panes of the splitter window. \docparam{window2}{The bottom pane.} -\docparam{sashPosition}{The initial position of the sash. If the value is -1, a default position -is chosen.} +\docparam{sashPosition}{The initial position of the sash. If this value is +positive, it specifies the size of the upper pane. If it's negative, it's +absolute value gives the size of the lower pane. Finally, specify 0 (default) +to choose the default position (half of the total window height).} \wxheading{Return value} @@ -274,8 +292,9 @@ TRUE if successful, FALSE otherwise (the window was already split). \wxheading{Remarks} -This should be called if you wish to initially view two panes. It can also be called at any subsequent time, -but the application should check that the window is not currently split using \helpref{IsSplit}{wxsplitterwindowissplit}. +This should be called if you wish to initially view two panes. It can also be +called at any subsequent time, but the application should check that the +window is not currently split using \helpref{IsSplit}{wxsplitterwindowissplit}. \wxheading{See also} @@ -285,7 +304,7 @@ but the application should check that the window is not currently split using \h \membersection{wxSplitterWindow::SplitVertically}\label{wxsplitterwindowsplitvertically} \func{bool}{SplitVertically}{\param{wxWindow* }{window1}, \param{wxWindow* }{window2}, - \param{int}{ sashPosition = -1}} + \param{int}{ sashPosition = 0}} Initializes the left and right panes of the splitter window. @@ -295,8 +314,10 @@ Initializes the left and right panes of the splitter window. \docparam{window2}{The right pane.} -\docparam{sashPosition}{The initial position of the sash. If the value is -1, a default position -is chosen.} +\docparam{sashPosition}{The initial position of the sash. If this value is +positive, it specifies the size of the left pane. If it's negative, it's +absolute value gives the size of the right pane. Finally, specify 0 (default) +to choose the default position (half of the total window width).} \wxheading{Return value} diff --git a/include/wx/generic/splitter.h b/include/wx/generic/splitter.h index f128338dc7..50781e4424 100644 --- a/include/wx/generic/splitter.h +++ b/include/wx/generic/splitter.h @@ -6,7 +6,7 @@ // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifndef __SPLITTERH_G__ @@ -46,32 +46,33 @@ class WXDLLEXPORT wxSplitterWindow: public wxWindow { - DECLARE_DYNAMIC_CLASS(wxSplitterWindow) - - public: +public: //////////////////////////////////////////////////////////////////////////// // Public API // Default constructor - wxSplitterWindow(void); + wxSplitterWindow(); // Normal constructor - wxSplitterWindow(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = wxSP_3D|wxCLIP_CHILDREN, const wxString& name = "splitter"); - ~wxSplitterWindow(void); + wxSplitterWindow(wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxSP_3D|wxCLIP_CHILDREN, + const wxString& name = "splitter"); + ~wxSplitterWindow(); // Gets the only or left/top pane - inline wxWindow *GetWindow1(void) { return m_windowOne; } + wxWindow *GetWindow1() const { return m_windowOne; } // Gets the right/bottom pane - inline wxWindow *GetWindow2(void) { return m_windowTwo; } + wxWindow *GetWindow2() const { return m_windowTwo; } // Sets the split mode - inline void SetSplitMode(int mode) { m_splitMode = mode; } + void SetSplitMode(int mode) { m_splitMode = mode; } // Gets the split mode - inline int GetSplitMode(void) const { return m_splitMode; }; + int GetSplitMode() const { return m_splitMode; }; // Initialize with one window void Initialize(wxWindow *window); @@ -79,38 +80,49 @@ class WXDLLEXPORT wxSplitterWindow: public wxWindow // Associates the given window with window 2, drawing the appropriate sash // and changing the split mode. // Does nothing and returns FALSE if the window is already split. - // A sashPosition of -1 means choose a default sash position. - bool SplitVertically(wxWindow *window1, wxWindow *window2, int sashPosition = -1); - bool SplitHorizontally(wxWindow *window1, wxWindow *window2, int sashPosition = -1); + // A sashPosition of 0 means choose a default sash position, + // negative sashPosition specifies the size of right/lower pane as it's + // absolute value rather than the size of left/upper pane. + bool SplitVertically(wxWindow *window1, + wxWindow *window2, + int sashPosition = 0); + bool SplitHorizontally(wxWindow *window1, + wxWindow *window2, + int sashPosition = 0); // Removes the specified (or second) window from the view // Doesn't actually delete the window. bool Unsplit(wxWindow *toRemove = (wxWindow *) NULL); // Is the window split? - inline bool IsSplit(void) const { return (m_windowTwo != NULL); } + bool IsSplit() const { return (m_windowTwo != NULL); } // Sets the sash size - inline void SetSashSize(int width) { m_sashSize = width; } + void SetSashSize(int width) { m_sashSize = width; } // Sets the border size - inline void SetBorderSize(int width) { m_borderSize = width; } + void SetBorderSize(int width) { m_borderSize = width; } // Gets the sash size - inline int GetSashSize(void) const { return m_sashSize; } + int GetSashSize() const { return m_sashSize; } // Gets the border size - inline int GetBorderSize(void) const { return m_borderSize; } + int GetBorderSize() const { return m_borderSize; } // Set the sash position void SetSashPosition(int position, bool redaw = TRUE); // Gets the sash position - inline int GetSashPosition(void) const { return m_sashPosition; } + int GetSashPosition() const { return m_sashPosition; } // If this is zero, we can remove panes by dragging the sash. - inline void SetMinimumPaneSize(int min) { m_minimumPaneSize = min; } - inline int GetMinimumPaneSize(void) const { return m_minimumPaneSize; } + void SetMinimumPaneSize(int min) { m_minimumPaneSize = min; } + int GetMinimumPaneSize() const { return m_minimumPaneSize; } + + // Called when the sash position is about to be changed, return + // FALSE from here to prevent the change from taking place. + // newSashPosition here is always positive or zero. + virtual bool OnSashPositionChange(int newSashPosition); // If the sash is moved to an extreme position, a subwindow // is removed from the splitter window, and the app is @@ -147,12 +159,12 @@ class WXDLLEXPORT wxSplitterWindow: public wxWindow bool SashHitTest(int x, int y, int tolerance = 2); // Resizes subwindows - void SizeWindows(void); + void SizeWindows(); // Initialize colours - void InitColours(void); + void InitColours(); - protected: +protected: int m_splitMode; wxWindow* m_windowOne; wxWindow* m_windowTwo; @@ -174,7 +186,10 @@ class WXDLLEXPORT wxSplitterWindow: public wxWindow wxPen* m_hilightPen; wxBrush* m_faceBrush; wxPen* m_facePen; -DECLARE_EVENT_TABLE() + +private: + DECLARE_DYNAMIC_CLASS(wxSplitterWindow) + DECLARE_EVENT_TABLE() }; -#endif +#endif // __SPLITTERH_G__ diff --git a/samples/splitter/test.cpp b/samples/splitter/test.cpp index 7c842ee0cc..33a25ed12a 100644 --- a/samples/splitter/test.cpp +++ b/samples/splitter/test.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: splitter.cpp +// Name: m_splitter.cpp // Purpose: wxSplitterWindow sample // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -29,36 +29,61 @@ class MyCanvas; class MyApp: public wxApp { public: - bool OnInit(); + bool OnInit(); +}; + +class MySplitterWindow : public wxSplitterWindow +{ +public: + MySplitterWindow(wxFrame *parent, wxWindowID id) : wxSplitterWindow(parent, id) + { + m_frame = parent; + } + + virtual bool OnSashPositionChange(int newSashPosition) + { + if ( !wxSplitterWindow::OnSashPositionChange(newSashPosition) ) + return FALSE; + + wxString str; + str.Printf("Sash position = %d", newSashPosition); + m_frame->SetStatusText(str); + + return TRUE; + } + +private: + wxFrame *m_frame; }; class MyFrame: public wxFrame { public: - MyFrame(wxFrame* frame, const wxString& title, const wxPoint& pos, const wxSize& size); - virtual ~MyFrame(); + MyFrame(wxFrame* frame, const wxString& title, const wxPoint& pos, const wxSize& size); + virtual ~MyFrame(); - bool OnClose(); + bool OnClose(); - // Menu commands - void SplitHorizontal(wxCommandEvent& event); - void SplitVertical(wxCommandEvent& event); - void Unsplit(wxCommandEvent& event); - void Quit(wxCommandEvent& event); + // Menu commands + void SplitHorizontal(wxCommandEvent& event); + void SplitVertical(wxCommandEvent& event); + void Unsplit(wxCommandEvent& event); + void SetMinSize(wxCommandEvent& event); + void Quit(wxCommandEvent& event); - // Menu command update functions - void UpdateUIHorizontal(wxUpdateUIEvent& event); - void UpdateUIVertical(wxUpdateUIEvent& event); - void UpdateUIUnsplit(wxUpdateUIEvent& event); - - void OnIdle(wxIdleEvent& event); + // Menu command update functions + void UpdateUIHorizontal(wxUpdateUIEvent& event); + void UpdateUIVertical(wxUpdateUIEvent& event); + void UpdateUIUnsplit(wxUpdateUIEvent& event); private: - wxMenu* fileMenu; - wxMenuBar* menuBar; - MyCanvas* leftCanvas; - MyCanvas* rightCanvas; - wxSplitterWindow* splitter; + void UpdatePosition(); + + wxMenu* fileMenu; + wxMenuBar* menuBar; + MyCanvas* m_leftCanvas; + MyCanvas* m_rightCanvas; + MySplitterWindow* m_splitter; DECLARE_EVENT_TABLE() }; @@ -69,7 +94,7 @@ public: MyCanvas(wxWindow* parent, wxWindowID id, int x, int y, int w, int h); virtual ~MyCanvas(); - virtual void OnDraw(wxDC& dc); + virtual void OnDraw(wxDC& dc); DECLARE_EVENT_TABLE() }; @@ -77,11 +102,15 @@ DECLARE_EVENT_TABLE() BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) END_EVENT_TABLE() -// ID for the menu quit command -#define SPLIT_QUIT 1 -#define SPLIT_HORIZONTAL 2 -#define SPLIT_VERTICAL 3 -#define SPLIT_UNSPLIT 4 +// ID for the menu commands +enum +{ + SPLIT_QUIT, + SPLIT_HORIZONTAL, + SPLIT_VERTICAL, + SPLIT_UNSPLIT, + SPLIT_SETMINSIZE +}; // Window ids #define SPLITTER_WINDOW 100 @@ -93,68 +122,63 @@ IMPLEMENT_APP(MyApp) bool MyApp::OnInit(void) { - MyFrame* frame = new MyFrame((wxFrame *) NULL, (char *) "wxSplitterWindow Example", wxPoint(50, 50), wxSize(400, 300)); + MyFrame* frame = new MyFrame((wxFrame *) NULL, "wxSplitterWindow Example", + wxPoint(50, 50), wxSize(420, 300)); - // Show the frame - frame->Show(TRUE); + // Show the frame + frame->Show(TRUE); - SetTopWindow(frame); + SetTopWindow(frame); - return TRUE; + return TRUE; } BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(SPLIT_VERTICAL, MyFrame::SplitVertical) - EVT_MENU(SPLIT_HORIZONTAL, MyFrame::SplitHorizontal) - EVT_MENU(SPLIT_UNSPLIT, MyFrame::Unsplit) - EVT_MENU(SPLIT_QUIT, MyFrame::Quit) - EVT_UPDATE_UI(SPLIT_VERTICAL, MyFrame::UpdateUIVertical) - EVT_UPDATE_UI(SPLIT_HORIZONTAL, MyFrame::UpdateUIHorizontal) - EVT_UPDATE_UI(SPLIT_UNSPLIT, MyFrame::UpdateUIUnsplit) - EVT_IDLE(MyFrame::OnIdle) + EVT_MENU(SPLIT_VERTICAL, MyFrame::SplitVertical) + EVT_MENU(SPLIT_HORIZONTAL, MyFrame::SplitHorizontal) + EVT_MENU(SPLIT_UNSPLIT, MyFrame::Unsplit) + EVT_MENU(SPLIT_QUIT, MyFrame::Quit) + EVT_MENU(SPLIT_SETMINSIZE, MyFrame::SetMinSize) + + EVT_UPDATE_UI(SPLIT_VERTICAL, MyFrame::UpdateUIVertical) + EVT_UPDATE_UI(SPLIT_HORIZONTAL, MyFrame::UpdateUIHorizontal) + EVT_UPDATE_UI(SPLIT_UNSPLIT, MyFrame::UpdateUIUnsplit) END_EVENT_TABLE() // My frame constructor MyFrame::MyFrame(wxFrame* frame, const wxString& title, const wxPoint& pos, const wxSize& size): wxFrame(frame, SPLITTER_FRAME, title, pos, size) { - // set the icon -#ifdef __WXMSW__ - SetIcon(wxIcon("mondrian")); -#endif + CreateStatusBar(2); - CreateStatusBar(1); + // Make a menubar + fileMenu = new wxMenu; + fileMenu->Append(SPLIT_VERTICAL, "Split &Vertically", "Split vertically"); + fileMenu->Append(SPLIT_HORIZONTAL, "Split &Horizontally", "Split horizontally"); + fileMenu->Append(SPLIT_UNSPLIT, "&Unsplit", "Unsplit"); + fileMenu->AppendSeparator(); + fileMenu->Append(SPLIT_SETMINSIZE, "Set &min size", "Set minimum pane size"); + fileMenu->AppendSeparator(); + fileMenu->Append(SPLIT_QUIT, "E&xit", "Exit"); - // Make a menubar - fileMenu = new wxMenu; - fileMenu->Append(SPLIT_VERTICAL, "Split &Vertically", "Split vertically"); - fileMenu->Append(SPLIT_HORIZONTAL, "Split &Horizontally", "Split horizontally"); - fileMenu->Append(SPLIT_UNSPLIT, "&Unsplit", "Unsplit"); - fileMenu->Append(SPLIT_QUIT, "E&xit", "Exit"); + menuBar = new wxMenuBar; + menuBar->Append(fileMenu, "&File"); - menuBar = new wxMenuBar; - menuBar->Append(fileMenu, "&File"); + SetMenuBar(menuBar); - SetMenuBar(menuBar); + m_splitter = new MySplitterWindow(this, SPLITTER_WINDOW); - splitter = new wxSplitterWindow(this, SPLITTER_WINDOW, wxPoint(0, 0), wxSize(400, 400), -// wxSP_BORDER); - wxSP_3D); -// wxSP_NOBORDER); + m_leftCanvas = new MyCanvas(m_splitter, CANVAS1, 0, 0, 400, 400); + m_leftCanvas->SetBackgroundColour(*wxRED); + m_leftCanvas->SetScrollbars(20, 20, 50, 50); - leftCanvas = new MyCanvas(splitter, CANVAS1, 0, 0, 400, 400); - leftCanvas->SetBackgroundColour(*wxRED); - leftCanvas->SetScrollbars(20, 20, 50, 50); + m_rightCanvas = new MyCanvas(m_splitter, CANVAS2, 0, 0, 400, 400); + m_rightCanvas->SetBackgroundColour(*wxCYAN); + m_rightCanvas->SetScrollbars(20, 20, 50, 50); + m_rightCanvas->Show(FALSE); - rightCanvas = new MyCanvas(splitter, CANVAS2, 0, 0, 400, 400); - rightCanvas->SetBackgroundColour(*wxCYAN); - rightCanvas->SetScrollbars(20, 20, 50, 50); - rightCanvas->Show(FALSE); - - splitter->Initialize(leftCanvas); - - // Set this to prevent unsplitting -// splitter->SetMinimumPaneSize(20); + m_splitter->Initialize(m_leftCanvas); + SetStatusText("Min pane size = 0", 1); } MyFrame::~MyFrame() @@ -163,59 +187,75 @@ MyFrame::~MyFrame() bool MyFrame::OnClose() { - return TRUE; + return TRUE; } void MyFrame::Quit(wxCommandEvent& WXUNUSED(event) ) { - Close(TRUE); + Close(TRUE); } void MyFrame::SplitHorizontal(wxCommandEvent& WXUNUSED(event) ) { - if ( splitter->IsSplit() ) - splitter->Unsplit(); - leftCanvas->Show(TRUE); - rightCanvas->Show(TRUE); - splitter->SplitHorizontally( leftCanvas, rightCanvas ); + if ( m_splitter->IsSplit() ) + m_splitter->Unsplit(); + m_leftCanvas->Show(TRUE); + m_rightCanvas->Show(TRUE); + m_splitter->SplitHorizontally( m_leftCanvas, m_rightCanvas ); + UpdatePosition(); } void MyFrame::SplitVertical(wxCommandEvent& WXUNUSED(event) ) { - if ( splitter->IsSplit() ) - splitter->Unsplit(); - leftCanvas->Show(TRUE); - rightCanvas->Show(TRUE); - splitter->SplitVertically( leftCanvas, rightCanvas ); + if ( m_splitter->IsSplit() ) + m_splitter->Unsplit(); + m_leftCanvas->Show(TRUE); + m_rightCanvas->Show(TRUE); + m_splitter->SplitVertically( m_leftCanvas, m_rightCanvas ); + UpdatePosition(); } void MyFrame::Unsplit(wxCommandEvent& WXUNUSED(event) ) { - if ( splitter->IsSplit() ) - splitter->Unsplit(); + if ( m_splitter->IsSplit() ) + m_splitter->Unsplit(); + SetStatusText("No splitter"); +} + +void MyFrame::SetMinSize(wxCommandEvent& WXUNUSED(event) ) +{ + wxString str; + str.Printf("%d", m_splitter->GetMinimumPaneSize()); + str = wxGetTextFromUser("Enter minimal size for panes:", "", str, this); + if ( str.IsEmpty() ) + return; + + int minsize = atoi(str); + m_splitter->SetMinimumPaneSize(minsize); + str.Printf("Min pane size = %d", minsize); + SetStatusText(str, 1); } void MyFrame::UpdateUIHorizontal(wxUpdateUIEvent& event) { - event.Enable( ( (!splitter->IsSplit()) || (splitter->GetSplitMode() != wxSPLIT_HORIZONTAL) ) ); + event.Enable( ( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_HORIZONTAL) ) ); } void MyFrame::UpdateUIVertical(wxUpdateUIEvent& event) { - event.Enable( ( (!splitter->IsSplit()) || (splitter->GetSplitMode() != wxSPLIT_VERTICAL) ) ); + event.Enable( ( (!m_splitter->IsSplit()) || (m_splitter->GetSplitMode() != wxSPLIT_VERTICAL) ) ); } void MyFrame::UpdateUIUnsplit(wxUpdateUIEvent& event) { - event.Enable( splitter->IsSplit() ); + event.Enable( m_splitter->IsSplit() ); } -void MyFrame::OnIdle(wxIdleEvent& event) +void MyFrame::UpdatePosition() { - if ( GetStatusBar()->GetStatusText(0) != "Ready" ) - SetStatusText("Ready"); - - wxFrame::OnIdle(event); + wxString str; + str.Printf("Sash position = %d", m_splitter->GetSashPosition()); + SetStatusText(str); } MyCanvas::MyCanvas(wxWindow* parent, wxWindowID id, int x, int y, int w, int h) : @@ -229,13 +269,13 @@ MyCanvas::~MyCanvas() void MyCanvas::OnDraw(wxDC& dc) { - dc.SetPen(*wxBLACK_PEN); - dc.DrawLine(0, 0, 100, 100); + dc.SetPen(*wxBLACK_PEN); + dc.DrawLine(0, 0, 100, 100); - dc.SetBackgroundMode(wxTRANSPARENT); - dc.DrawText("Testing", 50, 50); + dc.SetBackgroundMode(wxTRANSPARENT); + dc.DrawText("Testing", 50, 50); - dc.SetPen(*wxRED_PEN); - dc.SetBrush(*wxGREEN_BRUSH); - dc.DrawRectangle(120, 120, 100, 80); + dc.SetPen(*wxRED_PEN); + dc.SetBrush(*wxGREEN_BRUSH); + dc.DrawRectangle(120, 120, 100, 80); } diff --git a/src/generic/splitter.cpp b/src/generic/splitter.cpp index 764f9c4b6c..7f631aa457 100644 --- a/src/generic/splitter.cpp +++ b/src/generic/splitter.cpp @@ -6,7 +6,7 @@ // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -42,7 +42,7 @@ BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow) END_EVENT_TABLE() #endif -wxSplitterWindow::wxSplitterWindow(void) +wxSplitterWindow::wxSplitterWindow() { m_splitMode = wxSPLIT_VERTICAL; m_windowOne = (wxWindow *) NULL; @@ -67,9 +67,12 @@ wxSplitterWindow::wxSplitterWindow(void) m_minimumPaneSize = 0; } -wxSplitterWindow::wxSplitterWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, - const wxSize& size, long style, const wxString& name) - :wxWindow(parent, id, pos, size, style, name) +wxSplitterWindow::wxSplitterWindow(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) + : wxWindow(parent, id, pos, size, style, name) { m_splitMode = wxSPLIT_VERTICAL; m_windowOne = (wxWindow *) NULL; @@ -116,7 +119,7 @@ wxSplitterWindow::wxSplitterWindow(wxWindow *parent, wxWindowID id, const wxPoin // SetBackground(wxBLUE_BRUSH); } -wxSplitterWindow::~wxSplitterWindow(void) +wxSplitterWindow::~wxSplitterWindow() { delete m_sashCursorWE; delete m_sashCursorNS; @@ -143,17 +146,17 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) long x, y; event.Position(&x, &y); - if (event.LeftDown()) - { + if (event.LeftDown()) + { if ( SashHitTest(x, y) ) { - CaptureMouse(); + CaptureMouse(); - // Required for X to specify that - // that we wish to draw on top of all windows - // - and we optimise by specifying the area - // for creating the overlap window. - wxScreenDC::StartDrawingOnTop(this); + // Required for X to specify that + // that we wish to draw on top of all windows + // - and we optimise by specifying the area + // for creating the overlap window. + wxScreenDC::StartDrawingOnTop(this); // We don't say we're dragging yet; we leave that // decision for the Dragging() branch, to ensure @@ -162,7 +165,7 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) m_firstX = x; m_firstY = y; } - } + } else if ( event.LeftUp() && m_dragMode == wxSPLIT_DRAG_LEFT_DOWN ) { // Wasn't a proper drag @@ -172,11 +175,11 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) SetCursor(*wxSTANDARD_CURSOR); } - else if (event.LeftUp() && m_dragMode == wxSPLIT_DRAG_DRAGGING) - { + else if (event.LeftUp() && m_dragMode == wxSPLIT_DRAG_DRAGGING) + { // We can stop dragging now and see what we've got. m_dragMode = wxSPLIT_DRAG_NONE; - ReleaseMouse(); + ReleaseMouse(); // Erase old tracker DrawSashTracker(m_oldX, m_oldY); @@ -185,12 +188,10 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) wxScreenDC::EndDrawingOnTop(); int w, h; - GetClientSize(&w, &h); + GetClientSize(&w, &h); if ( m_splitMode == wxSPLIT_VERTICAL ) { - // First check if we should veto this resize because - // the pane size is too small - if ( wxMax(x, 0) < m_minimumPaneSize || wxMax((w - x), 0) < m_minimumPaneSize) + if ( !OnSashPositionChange(x) ) return; if ( x <= 4 ) @@ -218,9 +219,7 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) } else { - // First check if we should veto this resize because - // the pane size is too small - if ( wxMax(y, 0) < m_minimumPaneSize || wxMax((h - y), 0) < m_minimumPaneSize) + if ( !OnSashPositionChange(y) ) return; if ( y <= 4 ) @@ -247,36 +246,36 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) } } SizeWindows(); - } - else if (event.Moving() && !event.Dragging()) - { + } + else if (event.Moving() && !event.Dragging()) + { // Just change the cursor if required if ( SashHitTest(x, y) ) { - if ( m_splitMode == wxSPLIT_VERTICAL ) + if ( m_splitMode == wxSPLIT_VERTICAL ) { - SetCursor(*m_sashCursorWE); + SetCursor(*m_sashCursorWE); } else { - SetCursor(*m_sashCursorNS); + SetCursor(*m_sashCursorNS); } } else { - SetCursor(*wxSTANDARD_CURSOR); + SetCursor(*wxSTANDARD_CURSOR); } - } - else if ( (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) || + } + else if ( (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) || (event.Dragging() && SashHitTest(x, y, 4)) ) - { + { if ( m_splitMode == wxSPLIT_VERTICAL ) { - SetCursor(*m_sashCursorWE); + SetCursor(*m_sashCursorWE); } else { - SetCursor(*m_sashCursorNS); + SetCursor(*m_sashCursorNS); } // Detect that this is really a drag: we've moved more than 1 pixel either way @@ -300,7 +299,7 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event) } m_oldX = x; m_oldY = y; - } + } else if ( event.LeftDClick() ) { OnDoubleClickSash(x, y); @@ -418,8 +417,8 @@ void wxSplitterWindow::DrawSash(wxDC& dc) dc.DrawLine(m_sashPosition+m_sashSize-2, 1, m_sashPosition+m_sashSize-2, h-1); dc.SetPen(*m_darkShadowPen); - dc.DrawLine(m_sashPosition+m_sashSize-1, 2, m_sashPosition+m_sashSize-1, h-2); - } + dc.DrawLine(m_sashPosition+m_sashSize-1, 2, m_sashPosition+m_sashSize-1, h-2); + } else { dc.SetPen(*m_facePen); @@ -528,7 +527,7 @@ void wxSplitterWindow::DrawSashTracker(int x, int y) // Position and size subwindows. // Note that the border size applies to each subwindow, not // including the edges next to the sash. -void wxSplitterWindow::SizeWindows(void) +void wxSplitterWindow::SizeWindows() { int w, h; GetClientSize(&w, &h); @@ -551,10 +550,8 @@ void wxSplitterWindow::SizeWindows(void) int w2 = w - 2*m_borderSize - m_sashSize - w1; int h2 = h - 2*m_borderSize; - m_windowOne->SetSize(x1, y1, - w1, h1); - m_windowTwo->SetSize(x2, y2, - w2, h2); + m_windowOne->SetSize(x1, y1, w1, h1); + m_windowTwo->SetSize(x2, y2, w2, h2); } else { @@ -585,13 +582,18 @@ bool wxSplitterWindow::SplitVertically(wxWindow *window1, wxWindow *window2, int if ( IsSplit() ) return FALSE; + int w, h; + GetClientSize(&w, &h); + m_splitMode = wxSPLIT_VERTICAL; m_windowOne = window1; m_windowTwo = window2; - if ( sashPosition == -1 ) - m_sashPosition = 100; - else + if ( sashPosition > 0 ) m_sashPosition = sashPosition; + else if ( sashPosition < 0 ) + m_sashPosition = w - sashPosition; + else // default + m_sashPosition = w/2; SizeWindows(); @@ -603,13 +605,18 @@ bool wxSplitterWindow::SplitHorizontally(wxWindow *window1, wxWindow *window2, i if ( IsSplit() ) return FALSE; + int w, h; + GetClientSize(&w, &h); + m_splitMode = wxSPLIT_HORIZONTAL; m_windowOne = window1; m_windowTwo = window2; - if ( sashPosition == -1 ) - m_sashPosition = 100; - else + if ( sashPosition > 0 ) m_sashPosition = sashPosition; + else if ( sashPosition < 0 ) + m_sashPosition = h - sashPosition; + else // default + m_sashPosition = h/2; SizeWindows(); @@ -657,6 +664,31 @@ void wxSplitterWindow::SetSashPosition(int position, bool redraw) } } +bool wxSplitterWindow::OnSashPositionChange(int newSashPosition) +{ + // is the left/upper pane too small? + if ( newSashPosition < m_minimumPaneSize ) + return NULL; + + // is the right/lower pane too small? + int w, h; + GetClientSize(&w, &h); + + if ( m_splitMode == wxSPLIT_VERTICAL ) + { + if ( h - newSashPosition < m_minimumPaneSize ) + return FALSE; + } + else // m_splitMode = wxSPLIT_HORIZONTAL + { + if ( w - newSashPosition < m_minimumPaneSize ) + return FALSE; + } + + // it's ok to move sash + return TRUE; +} + // Called when the sash is double-clicked. // The default behaviour is to remove the sash if the // minimum pane size is zero. @@ -669,50 +701,39 @@ void wxSplitterWindow::OnDoubleClickSash(int WXUNUSED(x), int WXUNUSED(y) ) } // Initialize colours -void wxSplitterWindow::InitColours(void) +void wxSplitterWindow::InitColours() { - if ( m_facePen ) - delete m_facePen; - if ( m_faceBrush ) - delete m_faceBrush; - if ( m_mediumShadowPen ) - delete m_mediumShadowPen; - if ( m_darkShadowPen ) - delete m_darkShadowPen; - if ( m_lightShadowPen ) - delete m_lightShadowPen; - if ( m_hilightPen ) - delete m_hilightPen; + wxDELETE( m_facePen ); + wxDELETE( m_faceBrush ); + wxDELETE( m_mediumShadowPen ); + wxDELETE( m_darkShadowPen ); + wxDELETE( m_lightShadowPen ); + wxDELETE( m_hilightPen ); // Shadow colours #if defined(__WIN95__) -// COLORREF ref = ::GetSysColor(COLOR_3DFACE); // Normally light grey wxColour faceColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); m_facePen = new wxPen(faceColour, 1, wxSOLID); m_faceBrush = new wxBrush(faceColour, wxSOLID); -// ref = ::GetSysColor(COLOR_3DSHADOW); // Normally dark grey wxColour mediumShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW)); m_mediumShadowPen = new wxPen(mediumShadowColour, 1, wxSOLID); -// ref = ::GetSysColor(COLOR_3DDKSHADOW); // Normally black wxColour darkShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DDKSHADOW)); m_darkShadowPen = new wxPen(darkShadowColour, 1, wxSOLID); -// ref = ::GetSysColor(COLOR_3DLIGHT); // Normally light grey wxColour lightShadowColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT)); m_lightShadowPen = new wxPen(lightShadowColour, 1, wxSOLID); -// ref = ::GetSysColor(COLOR_3DHILIGHT); // Normally white wxColour hilightColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT)); m_hilightPen = new wxPen(hilightColour, 1, wxSOLID); -#else +#else // !Win32 m_facePen = new wxPen("LIGHT GREY", 1, wxSOLID); m_faceBrush = new wxBrush("LIGHT GREY", wxSOLID); m_mediumShadowPen = new wxPen("GREY", 1, wxSOLID); m_darkShadowPen = new wxPen("BLACK", 1, wxSOLID); m_lightShadowPen = new wxPen("LIGHT GREY", 1, wxSOLID); m_hilightPen = new wxPen("WHITE", 1, wxSOLID); -#endif +#endif // Win32/!Win32 }