]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/splitter.cpp
"continue;" restored to prevent the app from going into infinite loop
[wxWidgets.git] / src / generic / splitter.cpp
index 764f9c4b6cc5497049298fac957486b6f7418688..d43a1244d3762b2b09fb014b97e6443a5501af08 100644 (file)
@@ -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,54 +146,34 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
     long x, y;
     event.Position(&x, &y);
 
-       if (event.LeftDown())
-       {
+    if (event.LeftDown())
+    {
         if ( SashHitTest(x, y) )
         {
-               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);
-
-            // We don't say we're dragging yet; we leave that
-            // decision for the Dragging() branch, to ensure
-            // the user has dragged a little bit.
-            m_dragMode = wxSPLIT_DRAG_LEFT_DOWN;
-            m_firstX = x;
-            m_firstY = y;
-        }
-       }
-    else if ( event.LeftUp() && m_dragMode == wxSPLIT_DRAG_LEFT_DOWN )
-    {
-        // Wasn't a proper drag
-        ReleaseMouse();
-        wxScreenDC::EndDrawingOnTop();
-        m_dragMode = wxSPLIT_DRAG_NONE;
+            CaptureMouse();
 
-        SetCursor(*wxSTANDARD_CURSOR);
+            m_dragMode = wxSPLIT_DRAG_DRAGGING;
+           
+            DrawSashTracker(x, y);
+            m_oldX = x;
+            m_oldY = y;
+           return;
+        }
     }
-       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);
 
-        // End drawing on top (frees the window used for drawing
-        // over the screen)
-        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 )
@@ -216,11 +199,9 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
                 m_sashPosition = x;
             }
         }
-        else
+        else  // m_splitMode == wxSPLIT_VERTICAL
         {
-            // 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 )
@@ -245,69 +226,43 @@ void wxSplitterWindow::OnMouseEvent(wxMouseEvent& event)
             {
                 m_sashPosition = y;
             }
-        }
+        } // m_splitMode == wxSPLIT_VERTICAL
         SizeWindows();
-       }
-       else if (event.Moving() && !event.Dragging())
-       {
+    }  // left up && 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)) ||
-              (event.Dragging() && SashHitTest(x, y, 4)) )
-       {
-         if ( m_splitMode == wxSPLIT_VERTICAL )
-         {
-               SetCursor(*m_sashCursorWE);
-         }
-         else
-         {
-               SetCursor(*m_sashCursorNS);
-         }
-
-        // Detect that this is really a drag: we've moved more than 1 pixel either way
-        if ((m_dragMode == wxSPLIT_DRAG_LEFT_DOWN) &&
-//                (abs((int)x - m_firstX) > 1 || abs((int)y - m_firstY) > 1) )
-                (abs((int)x - m_firstX) > 0 || abs((int)y - m_firstY) > 1) )
-        {
-            m_dragMode = wxSPLIT_DRAG_DRAGGING;
-            DrawSashTracker(x, y);
-        }
-        else
-        {
-          if ( m_dragMode == wxSPLIT_DRAG_DRAGGING )
-          {
-            // Erase old tracker
-            DrawSashTracker(m_oldX, m_oldY);
+    }
+    else if (event.Dragging() && (m_dragMode == wxSPLIT_DRAG_DRAGGING)) 
+    {
+        // Erase old tracker
+        DrawSashTracker(m_oldX, m_oldY);
+
+        // Draw new one
+        DrawSashTracker(x, y);
 
-            // Draw new one
-            DrawSashTracker(x, y);
-          }
-        }
         m_oldX = x;
         m_oldY = y;
-       }
+    }
     else if ( event.LeftDClick() )
     {
         OnDoubleClickSash(x, y);
     }
-    else
-    {
-    }
 }
 
 void wxSplitterWindow::OnSize(wxSizeEvent& WXUNUSED(event))
@@ -418,8 +373,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 +483,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 +506,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 +538,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 +561,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();
 
@@ -624,25 +587,54 @@ bool wxSplitterWindow::Unsplit(wxWindow *toRemove)
     if ( ! IsSplit() )
         return FALSE;
 
+    wxWindow *win = NULL;
     if ( toRemove == NULL || toRemove == m_windowTwo)
     {
-        wxWindow *win = m_windowTwo ;
+        win = m_windowTwo ;
         m_windowTwo = (wxWindow *) NULL;
-        m_sashPosition = 0;
-        OnUnsplit(win);
-        SizeWindows();
     }
     else if ( toRemove == m_windowOne )
     {
-        wxWindow *win = m_windowOne ;
+        win = m_windowOne ;
         m_windowOne = m_windowTwo;
         m_windowTwo = (wxWindow *) NULL;
-        m_sashPosition = 0;
-        OnUnsplit(win);
-        SizeWindows();
     }
     else
+    {
+        wxFAIL_MSG("splitter: attempt to remove a non-existent window");
+
         return FALSE;
+    }
+
+    OnUnsplit(win);
+    m_sashPosition = 0;
+    SizeWindows();
+
+    return TRUE;
+}
+
+// Replace a window with another one
+bool wxSplitterWindow::ReplaceWindow(wxWindow *winOld, wxWindow *winNew)
+{
+    wxCHECK_MSG( winOld, FALSE, "use one of Split() functions instead" );
+    wxCHECK_MSG( winNew, FALSE, "use Unsplit() functions instead" );
+
+    if ( winOld == m_windowTwo )
+    {
+        m_windowTwo = winNew;
+    }
+    else if ( winOld == m_windowOne )
+    {
+        m_windowOne = winNew;
+    }
+    else
+    {
+        wxFAIL_MSG("splitter: attempt to replace a non-existent window");
+
+        return FALSE;
+    }
+
+    SizeWindows();
 
     return TRUE;
 }
@@ -657,6 +649,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 ( w - newSashPosition < m_minimumPaneSize )
+      return FALSE;
+  }
+  else // m_splitMode = wxSPLIT_HORIZONTAL
+  {
+    if ( h - 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 +686,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
 }