home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / sashwin.cpp < prev    next >
C/C++ Source or Header  |  2002-09-21  |  21KB  |  725 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        sashwin.cpp
  3. // Purpose:     wxSashWindow implementation. A sash window has an optional
  4. //              sash on each edge, allowing it to be dragged. An event
  5. //              is generated when the sash is released.
  6. // Author:      Julian Smart
  7. // Modified by:
  8. // Created:     01/02/97
  9. // RCS-ID:      $Id: sashwin.cpp,v 1.32.2.1 2002/09/21 14:16:24 JS Exp $
  10. // Copyright:   (c) Julian Smart
  11. // Licence:     wxWindows license
  12. /////////////////////////////////////////////////////////////////////////////
  13.  
  14. #ifdef __GNUG__
  15. #pragma implementation "sashwin.h"
  16. #endif
  17.  
  18. // For compilers that support precompilation, includes "wx.h".
  19. #include "wx/wxprec.h"
  20.  
  21. #ifdef __BORLANDC__
  22. #pragma hdrstop
  23. #endif
  24.  
  25. #if wxUSE_SASH
  26.  
  27. #ifndef WX_PRECOMP
  28.     #include "wx/dialog.h"
  29.     #include "wx/frame.h"
  30.     #include "wx/settings.h"
  31. #endif
  32.  
  33. #include <math.h>
  34. #include <stdlib.h>
  35.  
  36. #include "wx/dcscreen.h"
  37. #include "wx/sashwin.h"
  38. #include "wx/laywin.h"
  39.  
  40. DEFINE_EVENT_TYPE(wxEVT_SASH_DRAGGED)
  41.  
  42. IMPLEMENT_DYNAMIC_CLASS(wxSashWindow, wxWindow)
  43. IMPLEMENT_DYNAMIC_CLASS(wxSashEvent, wxCommandEvent)
  44.  
  45. BEGIN_EVENT_TABLE(wxSashWindow, wxWindow)
  46.     EVT_PAINT(wxSashWindow::OnPaint)
  47.     EVT_SIZE(wxSashWindow::OnSize)
  48.     EVT_MOUSE_EVENTS(wxSashWindow::OnMouseEvent)
  49. #ifdef __WXMSW__
  50.     EVT_SET_CURSOR(wxSashWindow::OnSetCursor)
  51. #endif // wxMSW
  52.  
  53. END_EVENT_TABLE()
  54.  
  55. bool wxSashWindow::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos,
  56.     const wxSize& size, long style, const wxString& name)
  57. {
  58.     return wxWindow::Create(parent, id, pos, size, style, name);
  59. }
  60.  
  61. wxSashWindow::~wxSashWindow()
  62. {
  63.     delete m_sashCursorWE;
  64.     delete m_sashCursorNS;
  65. }
  66.  
  67. void wxSashWindow::Init()
  68. {
  69.     m_draggingEdge = wxSASH_NONE;
  70.     m_dragMode = wxSASH_DRAG_NONE;
  71.     m_oldX = 0;
  72.     m_oldY = 0;
  73.     m_firstX = 0;
  74.     m_firstY = 0;
  75.     m_borderSize = 3;
  76.     m_extraBorderSize = 0;
  77.     m_minimumPaneSizeX = 0;
  78.     m_minimumPaneSizeY = 0;
  79.     m_maximumPaneSizeX = 10000;
  80.     m_maximumPaneSizeY = 10000;
  81.     m_sashCursorWE = new wxCursor(wxCURSOR_SIZEWE);
  82.     m_sashCursorNS = new wxCursor(wxCURSOR_SIZENS);
  83.     m_mouseCaptured = FALSE;
  84.     m_currentCursor = NULL;
  85.  
  86.     // Eventually, we'll respond to colour change messages
  87.     InitColours();
  88. }
  89.  
  90. void wxSashWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
  91. {
  92.     wxPaintDC dc(this);
  93.  
  94.     DrawBorders(dc);
  95.     DrawSashes(dc);
  96. }
  97.  
  98. void wxSashWindow::OnMouseEvent(wxMouseEvent& event)
  99. {
  100.     wxCoord x, y;
  101.     event.GetPosition(&x, &y);
  102.  
  103.     wxSashEdgePosition sashHit = SashHitTest(x, y);
  104.  
  105.     if (event.LeftDown())
  106.     {
  107.         CaptureMouse();
  108.         m_mouseCaptured = TRUE;
  109.  
  110.         if ( sashHit != wxSASH_NONE )
  111.         {
  112.             // Required for X to specify that
  113.             // that we wish to draw on top of all windows
  114.             // - and we optimise by specifying the area
  115.             // for creating the overlap window.
  116.             // Find the first frame or dialog and use this to specify
  117.             // the area to draw on.
  118.             wxWindow* parent = this;
  119.  
  120.             while (parent && !parent->IsKindOf(CLASSINFO(wxDialog)) &&
  121.                              !parent->IsKindOf(CLASSINFO(wxFrame)))
  122.               parent = parent->GetParent();
  123.  
  124.             wxScreenDC::StartDrawingOnTop(parent);
  125.  
  126.             // We don't say we're dragging yet; we leave that
  127.             // decision for the Dragging() branch, to ensure
  128.             // the user has dragged a little bit.
  129.             m_dragMode = wxSASH_DRAG_LEFT_DOWN;
  130.             m_draggingEdge = sashHit;
  131.             m_firstX = x;
  132.             m_firstY = y;
  133.  
  134.             if ( (sashHit == wxSASH_LEFT) || (sashHit == wxSASH_RIGHT) )
  135.             {
  136.                 if (m_currentCursor != m_sashCursorWE)
  137.                 {
  138.                     SetCursor(*m_sashCursorWE);
  139.                 }
  140.                 m_currentCursor = m_sashCursorWE;
  141.             }
  142.             else
  143.             {
  144.                 if (m_currentCursor != m_sashCursorNS)
  145.                 {
  146.                     SetCursor(*m_sashCursorNS);
  147.                 }
  148.                 m_currentCursor = m_sashCursorNS;
  149.             }
  150.         }
  151.     }
  152.     else if ( event.LeftUp() && m_dragMode == wxSASH_DRAG_LEFT_DOWN )
  153.     {
  154.         // Wasn't a proper drag
  155.         if (m_mouseCaptured)
  156.             ReleaseMouse();
  157.         m_mouseCaptured = FALSE;
  158.  
  159.         wxScreenDC::EndDrawingOnTop();
  160.         m_dragMode = wxSASH_DRAG_NONE;
  161.         m_draggingEdge = wxSASH_NONE;
  162.     }
  163.     else if (event.LeftUp() && m_dragMode == wxSASH_DRAG_DRAGGING)
  164.     {
  165.         // We can stop dragging now and see what we've got.
  166.         m_dragMode = wxSASH_DRAG_NONE;
  167.         if (m_mouseCaptured)
  168.             ReleaseMouse();
  169.         m_mouseCaptured = FALSE;
  170.  
  171.         // Erase old tracker
  172.         DrawSashTracker(m_draggingEdge, m_oldX, m_oldY);
  173.  
  174.         // End drawing on top (frees the window used for drawing
  175.         // over the screen)
  176.         wxScreenDC::EndDrawingOnTop();
  177.  
  178.         int w, h;
  179.         GetSize(&w, &h);
  180.         int xp, yp;
  181.         GetPosition(&xp, &yp);
  182.  
  183.         wxSashEdgePosition edge = m_draggingEdge;
  184.         m_draggingEdge = wxSASH_NONE;
  185.  
  186.         wxRect dragRect;
  187.         wxSashDragStatus status = wxSASH_STATUS_OK;
  188.  
  189.         // the new height and width of the window - if -1, it didn't change
  190.         int newHeight = -1,
  191.             newWidth = -1;
  192.  
  193.         // NB: x and y may be negative and they're relative to the sash window
  194.         //     upper left corner, while xp and yp are expressed in the parent
  195.         //     window system of coordinates, so adjust them! After this
  196.         //     adjustment, all coordinates are relative to the parent window.
  197.         y += yp;
  198.         x += xp;
  199.  
  200.         switch (edge)
  201.         {
  202.             case wxSASH_TOP:
  203.                 if ( y > yp + h )
  204.                 {
  205.                     // top sash shouldn't get below the bottom one
  206.                     status = wxSASH_STATUS_OUT_OF_RANGE;
  207.                 }
  208.                 else
  209.                 {
  210.                     newHeight = h - (y - yp);
  211.                 }
  212.                 break;
  213.  
  214.             case wxSASH_BOTTOM:
  215.                 if ( y < yp )
  216.                 {
  217.                     // bottom sash shouldn't get above the top one
  218.                     status = wxSASH_STATUS_OUT_OF_RANGE;
  219.                 }
  220.                 else
  221.                 {
  222.                     newHeight = y - yp;
  223.                 }
  224.                 break;
  225.  
  226.             case wxSASH_LEFT:
  227.                 if ( x > xp + w )
  228.                 {
  229.                     // left sash shouldn't get beyond the right one
  230.                     status = wxSASH_STATUS_OUT_OF_RANGE;
  231.                 }
  232.                 else
  233.                 {
  234.                     newWidth = w - (x - xp);
  235.                 }
  236.                 break;
  237.  
  238.             case wxSASH_RIGHT:
  239.                 if ( x < xp )
  240.                 {
  241.                     // and the right sash, finally, shouldn't be beyond the
  242.                     // left one
  243.                     status = wxSASH_STATUS_OUT_OF_RANGE;
  244.                 }
  245.                 else
  246.                 {
  247.                     newWidth = x - xp;
  248.                 }
  249.                 break;
  250.  
  251.             case wxSASH_NONE:
  252.                 // can this happen at all?
  253.                 break;
  254.         }
  255.  
  256.         if ( newHeight == -1 )
  257.         {
  258.             // didn't change
  259.             newHeight = h;
  260.         }
  261.         else
  262.         {
  263.             // make sure it's in m_minimumPaneSizeY..m_maximumPaneSizeY range
  264.             newHeight = wxMax(newHeight, m_minimumPaneSizeY);
  265.             newHeight = wxMin(newHeight, m_maximumPaneSizeY);
  266.         }
  267.  
  268.         if ( newWidth == -1 )
  269.         {
  270.             // didn't change
  271.             newWidth = w;
  272.         }
  273.         else
  274.         {
  275.             // make sure it's in m_minimumPaneSizeY..m_maximumPaneSizeY range
  276.             newWidth = wxMax(newWidth, m_minimumPaneSizeX);
  277.             newWidth = wxMin(newWidth, m_maximumPaneSizeX);
  278.         }
  279.  
  280.         dragRect = wxRect(x, y, newWidth, newHeight);
  281.  
  282.         wxSashEvent event(GetId(), edge);
  283.         event.SetEventObject(this);
  284.         event.SetDragStatus(status);
  285.         event.SetDragRect(dragRect);
  286.         GetEventHandler()->ProcessEvent(event);
  287.     }
  288.     else if ( event.LeftUp() )
  289.     {
  290.         if (m_mouseCaptured)
  291.            ReleaseMouse();
  292.         m_mouseCaptured = FALSE;
  293.     }
  294.     else if (event.Moving() && !event.Dragging())
  295.     {
  296.         // Just change the cursor if required
  297.         if ( sashHit != wxSASH_NONE )
  298.         {
  299.             if ( (sashHit == wxSASH_LEFT) || (sashHit == wxSASH_RIGHT) )
  300.             {
  301.                 if (m_currentCursor != m_sashCursorWE)
  302.                 {
  303.                     SetCursor(*m_sashCursorWE);
  304.                 }
  305.                 m_currentCursor = m_sashCursorWE;
  306.             }
  307.             else
  308.             {
  309.                 if (m_currentCursor != m_sashCursorNS)
  310.                 {
  311.                     SetCursor(*m_sashCursorNS);
  312.                 }
  313.                 m_currentCursor = m_sashCursorNS;
  314.             }
  315.         }
  316.         else
  317.         {
  318.             SetCursor(wxNullCursor);
  319.             m_currentCursor = NULL;
  320.         }
  321.     }
  322.     else if ( event.Dragging() &&
  323.               ((m_dragMode == wxSASH_DRAG_DRAGGING) ||
  324.                (m_dragMode == wxSASH_DRAG_LEFT_DOWN)) )
  325.     {
  326.         if ( (m_draggingEdge == wxSASH_LEFT) || (m_draggingEdge == wxSASH_RIGHT) )
  327.         {
  328.             if (m_currentCursor != m_sashCursorWE)
  329.             {
  330.                 SetCursor(*m_sashCursorWE);
  331.             }
  332.             m_currentCursor = m_sashCursorWE;
  333.         }
  334.         else
  335.         {
  336.             if (m_currentCursor != m_sashCursorNS)
  337.             {
  338.                 SetCursor(*m_sashCursorNS);
  339.             }
  340.             m_currentCursor = m_sashCursorNS;
  341.         }
  342.  
  343.         if (m_dragMode == wxSASH_DRAG_LEFT_DOWN)
  344.         {
  345.             m_dragMode = wxSASH_DRAG_DRAGGING;
  346.             DrawSashTracker(m_draggingEdge, x, y);
  347.         }
  348.         else
  349.         {
  350.             if ( m_dragMode == wxSASH_DRAG_DRAGGING )
  351.             {
  352.                 // Erase old tracker
  353.                 DrawSashTracker(m_draggingEdge, m_oldX, m_oldY);
  354.  
  355.                 // Draw new one
  356.                 DrawSashTracker(m_draggingEdge, x, y);
  357.             }
  358.         }
  359.         m_oldX = x;
  360.         m_oldY = y;
  361.     }
  362.     else if ( event.LeftDClick() )
  363.     {
  364.         // Nothing
  365.     }
  366.     else
  367.     {
  368.     }
  369. }
  370.  
  371. void wxSashWindow::OnSize(wxSizeEvent& WXUNUSED(event))
  372. {
  373.     SizeWindows();
  374. }
  375.  
  376. wxSashEdgePosition wxSashWindow::SashHitTest(int x, int y, int WXUNUSED(tolerance))
  377. {
  378.     int cx, cy;
  379.     GetClientSize(& cx, & cy);
  380.  
  381.     int i;
  382.     for (i = 0; i < 4; i++)
  383.     {
  384.         wxSashEdge& edge = m_sashes[i];
  385.         wxSashEdgePosition position = (wxSashEdgePosition) i ;
  386.  
  387.         if (edge.m_show)
  388.         {
  389.             switch (position)
  390.             {
  391.                 case wxSASH_TOP:
  392.                 {
  393.                     if (y >= 0 && y <= GetEdgeMargin(position))
  394.                         return wxSASH_TOP;
  395.                     break;
  396.                 }
  397.                 case wxSASH_RIGHT:
  398.                 {
  399.                     if ((x >= cx - GetEdgeMargin(position)) && (x <= cx))
  400.                         return wxSASH_RIGHT;
  401.                     break;
  402.                 }
  403.                 case wxSASH_BOTTOM:
  404.                 {
  405.                     if ((y >= cy - GetEdgeMargin(position)) && (y <= cy))
  406.                         return wxSASH_BOTTOM;
  407.                     break;
  408.                 }
  409.                 case wxSASH_LEFT:
  410.                 {
  411.                     if ((x <= GetEdgeMargin(position)) && (x >= 0))
  412.                         return wxSASH_LEFT;
  413.                     break;
  414.                 }
  415.                 case wxSASH_NONE:
  416.                 {
  417.                     break;
  418.                 }
  419.             }
  420.         }
  421.     }
  422.     return wxSASH_NONE;
  423. }
  424.  
  425. // Draw 3D effect borders
  426. void wxSashWindow::DrawBorders(wxDC& dc)
  427. {
  428.     int w, h;
  429.     GetClientSize(&w, &h);
  430.  
  431.     wxPen mediumShadowPen(m_mediumShadowColour, 1, wxSOLID);
  432.     wxPen darkShadowPen(m_darkShadowColour, 1, wxSOLID);
  433.     wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID);
  434.     wxPen hilightPen(m_hilightColour, 1, wxSOLID);
  435.  
  436.     if ( GetWindowStyleFlag() & wxSW_3DBORDER )
  437.     {
  438.         dc.SetPen(mediumShadowPen);
  439.         dc.DrawLine(0, 0, w-1, 0);
  440.         dc.DrawLine(0, 0, 0, h - 1);
  441.  
  442.         dc.SetPen(darkShadowPen);
  443.         dc.DrawLine(1, 1, w-2, 1);
  444.         dc.DrawLine(1, 1, 1, h-2);
  445.  
  446.         dc.SetPen(hilightPen);
  447.         dc.DrawLine(0, h-1, w-1, h-1);
  448.         dc.DrawLine(w-1, 0, w-1, h); // Surely the maximum y pos. should be h - 1.
  449.                                      /// Anyway, h is required for MSW.
  450.  
  451.         dc.SetPen(lightShadowPen);
  452.         dc.DrawLine(w-2, 1, w-2, h-2); // Right hand side
  453.         dc.DrawLine(1, h-2, w-1, h-2);     // Bottom
  454.     }
  455.     else if ( GetWindowStyleFlag() & wxSW_BORDER )
  456.     {
  457.         dc.SetBrush(*wxTRANSPARENT_BRUSH);
  458.         dc.SetPen(*wxBLACK_PEN);
  459.         dc.DrawRectangle(0, 0, w-1, h-1);
  460.     }
  461.  
  462.     dc.SetPen(wxNullPen);
  463.     dc.SetBrush(wxNullBrush);
  464. }
  465.  
  466. void wxSashWindow::DrawSashes(wxDC& dc)
  467. {
  468.     int i;
  469.     for (i = 0; i < 4; i++)
  470.         if (m_sashes[i].m_show)
  471.             DrawSash((wxSashEdgePosition) i, dc);
  472. }
  473.  
  474. // Draw the sash
  475. void wxSashWindow::DrawSash(wxSashEdgePosition edge, wxDC& dc)
  476. {
  477.     int w, h;
  478.     GetClientSize(&w, &h);
  479.  
  480.     wxPen facePen(m_faceColour, 1, wxSOLID);
  481.     wxBrush faceBrush(m_faceColour, wxSOLID);
  482.     wxPen mediumShadowPen(m_mediumShadowColour, 1, wxSOLID);
  483.     wxPen darkShadowPen(m_darkShadowColour, 1, wxSOLID);
  484.     wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID);
  485.     wxPen hilightPen(m_hilightColour, 1, wxSOLID);
  486.     wxPen blackPen(wxColour(0, 0, 0), 1, wxSOLID);
  487.     wxPen whitePen(wxColour(255, 255, 255), 1, wxSOLID);
  488.  
  489.     if ( edge == wxSASH_LEFT || edge == wxSASH_RIGHT )
  490.     {
  491.         int sashPosition = 0;
  492.         if (edge == wxSASH_LEFT)
  493.             sashPosition = 0;
  494.         else
  495.             sashPosition = w - GetEdgeMargin(edge);
  496.  
  497.         dc.SetPen(facePen);
  498.         dc.SetBrush(faceBrush);
  499.         dc.DrawRectangle(sashPosition, 0, GetEdgeMargin(edge), h);
  500.  
  501.         if (GetWindowStyleFlag() & wxSW_3DSASH)
  502.         {
  503.             if (edge == wxSASH_LEFT)
  504.             {
  505.                 // Draw a dark grey line on the left to indicate that the
  506.                 // sash is raised
  507.                 dc.SetPen(mediumShadowPen);
  508.                 dc.DrawLine(GetEdgeMargin(edge), 0, GetEdgeMargin(edge), h);
  509.             }
  510.             else
  511.             {
  512.                 // Draw a highlight line on the right to indicate that the
  513.                 // sash is raised
  514.                 dc.SetPen(hilightPen);
  515.                 dc.DrawLine(w - GetEdgeMargin(edge), 0, w - GetEdgeMargin(edge), h);
  516.             }
  517.         }
  518.     }
  519.     else // top or bottom
  520.     {
  521.         int sashPosition = 0;
  522.         if (edge == wxSASH_TOP)
  523.             sashPosition = 0;
  524.         else
  525.             sashPosition = h - GetEdgeMargin(edge);
  526.  
  527.         dc.SetPen(facePen);
  528.         dc.SetBrush(faceBrush);
  529.         dc.DrawRectangle(0, sashPosition, w, GetEdgeMargin(edge));
  530.  
  531.         if (GetWindowStyleFlag() & wxSW_3DSASH)
  532.         {
  533.             if (edge == wxSASH_BOTTOM)
  534.             {
  535.                 // Draw a highlight line on the bottom to indicate that the
  536.                 // sash is raised
  537.                 dc.SetPen(hilightPen);
  538.                 dc.DrawLine(0, h - GetEdgeMargin(edge), w, h - GetEdgeMargin(edge));
  539.             }
  540.             else
  541.             {
  542.                 // Draw a drak grey line on the top to indicate that the
  543.                 // sash is raised
  544.                 dc.SetPen(mediumShadowPen);
  545.                 dc.DrawLine(1, GetEdgeMargin(edge), w-1, GetEdgeMargin(edge));
  546.             }
  547.         }
  548.     }
  549.  
  550.     dc.SetPen(wxNullPen);
  551.     dc.SetBrush(wxNullBrush);
  552. }
  553.  
  554. // Draw the sash tracker (for whilst moving the sash)
  555. void wxSashWindow::DrawSashTracker(wxSashEdgePosition edge, int x, int y)
  556. {
  557.     int w, h;
  558.     GetClientSize(&w, &h);
  559.  
  560.     wxScreenDC screenDC;
  561.     int x1, y1;
  562.     int x2, y2;
  563.  
  564.     if ( edge == wxSASH_LEFT || edge == wxSASH_RIGHT )
  565.     {
  566.         x1 = x; y1 = 2;
  567.         x2 = x; y2 = h-2;
  568.  
  569.         if ( (edge == wxSASH_LEFT) && (x1 > w) )
  570.         {
  571.             x1 = w; x2 = w;
  572.         }
  573.         else if ( (edge == wxSASH_RIGHT) && (x1 < 0) )
  574.         {
  575.             x1 = 0; x2 = 0;
  576.         }
  577.     }
  578.     else
  579.     {
  580.         x1 = 2; y1 = y;
  581.         x2 = w-2; y2 = y;
  582.  
  583.         if ( (edge == wxSASH_TOP) && (y1 > h) )
  584.         {
  585.             y1 = h;
  586.             y2 = h;
  587.         }
  588.         else if ( (edge == wxSASH_BOTTOM) && (y1 < 0) )
  589.         {
  590.             y1 = 0;
  591.             y2 = 0;
  592.         }
  593.     }
  594.  
  595.     ClientToScreen(&x1, &y1);
  596.     ClientToScreen(&x2, &y2);
  597.  
  598.     wxPen sashTrackerPen(*wxBLACK, 2, wxSOLID);
  599.  
  600.     screenDC.SetLogicalFunction(wxINVERT);
  601.     screenDC.SetPen(sashTrackerPen);
  602.     screenDC.SetBrush(*wxTRANSPARENT_BRUSH);
  603.  
  604.     screenDC.DrawLine(x1, y1, x2, y2);
  605.  
  606.     screenDC.SetLogicalFunction(wxCOPY);
  607.  
  608.     screenDC.SetPen(wxNullPen);
  609.     screenDC.SetBrush(wxNullBrush);
  610. }
  611.  
  612. // Position and size subwindows.
  613. // Note that the border size applies to each subwindow, not
  614. // including the edges next to the sash.
  615. void wxSashWindow::SizeWindows()
  616. {
  617.     int cw, ch;
  618.     GetClientSize(&cw, &ch);
  619.  
  620.     if (GetChildren().Number() == 1)
  621.     {
  622.         wxWindow* child = (wxWindow*) (GetChildren().First()->Data());
  623.  
  624.         int x = 0;
  625.         int y = 0;
  626.         int width = cw;
  627.         int height = ch;
  628.  
  629.         // Top
  630.         if (m_sashes[0].m_show)
  631.         {
  632.             y = m_borderSize;
  633.             height -= m_borderSize;
  634.         }
  635.         y += m_extraBorderSize;
  636.  
  637.         // Left
  638.         if (m_sashes[3].m_show)
  639.         {
  640.             x = m_borderSize;
  641.             width -= m_borderSize;
  642.         }
  643.         x += m_extraBorderSize;
  644.  
  645.         // Right
  646.         if (m_sashes[1].m_show)
  647.         {
  648.             width -= m_borderSize;
  649.         }
  650.         width -= 2*m_extraBorderSize;
  651.  
  652.         // Bottom
  653.         if (m_sashes[2].m_show)
  654.         {
  655.             height -= m_borderSize;
  656.         }
  657.         height -= 2*m_extraBorderSize;
  658.  
  659.         child->SetSize(x, y, width, height);
  660.     }
  661.     else if (GetChildren().Number() > 1)
  662.     {
  663.         // Perhaps multiple children are themselves sash windows.
  664.         // TODO: this doesn't really work because the subwindows sizes/positions
  665.         // must be set to leave a gap for the parent's sash (hit-test and decorations).
  666.         // Perhaps we can allow for this within LayoutWindow, testing whether the parent
  667.         // is a sash window, and if so, allowing some space for the edges.
  668.         wxLayoutAlgorithm layout;
  669.         layout.LayoutWindow(this);
  670.     }
  671.  
  672.     wxClientDC dc(this);
  673.     DrawBorders(dc);
  674.     DrawSashes(dc);
  675. }
  676.  
  677. // Initialize colours
  678. void wxSashWindow::InitColours()
  679. {
  680.     // Shadow colours
  681. #ifndef __WIN16__
  682.     m_faceColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
  683.     m_mediumShadowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW);
  684.     m_darkShadowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW);
  685.     m_lightShadowColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
  686.     m_hilightColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT);
  687. #else
  688.     m_faceColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
  689.     m_mediumShadowColour = *(wxTheColourDatabase->FindColour("GREY"));
  690.     m_darkShadowColour = *(wxTheColourDatabase->FindColour("BLACK"));
  691.     m_lightShadowColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
  692.     m_hilightColour = *(wxTheColourDatabase->FindColour("WHITE"));
  693. #endif
  694. }
  695.  
  696. void wxSashWindow::SetSashVisible(wxSashEdgePosition edge, bool sash)
  697. {
  698.      m_sashes[edge].m_show = sash;
  699.      if (sash)
  700.         m_sashes[edge].m_margin = m_borderSize;
  701.      else
  702.         m_sashes[edge].m_margin = 0;
  703. }
  704.  
  705. #ifdef __WXMSW__
  706.  
  707. // this is currently called (and needed) under MSW only...
  708. void wxSashWindow::OnSetCursor(wxSetCursorEvent& event)
  709. {
  710.     // if we don't do it, the resizing cursor might be set for child window:
  711.     // and like this we explicitly say that our cursor should not be used for
  712.     // children windows which overlap us
  713.  
  714.     if ( SashHitTest(event.GetX(), event.GetY()) != wxSASH_NONE)
  715.     {
  716.         // default processing is ok
  717.         event.Skip();
  718.     }
  719.     //else: do nothing, in particular, don't call Skip()
  720. }
  721.  
  722. #endif // wxMSW
  723.  
  724. #endif // wxUSE_SASH
  725.