X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b412f9be504e07559a98ae234f30bb1bd0b2aa1f..8f974c520a8733158591891458fda10fae4c3950:/src/generic/sashwin.cpp diff --git a/src/generic/sashwin.cpp b/src/generic/sashwin.cpp index 831085a907..8d679953df 100644 --- a/src/generic/sashwin.cpp +++ b/src/generic/sashwin.cpp @@ -8,7 +8,7 @@ // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Julian Smart -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -22,18 +22,23 @@ #pragma hdrstop #endif +#if wxUSE_SASH + #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/dialog.h" + #include "wx/frame.h" + #include "wx/settings.h" #endif #include #include -#include "wx/string.h" #include "wx/dcscreen.h" #include "wx/sashwin.h" +#include "wx/laywin.h" + +DEFINE_EVENT_TYPE(wxEVT_SASH_DRAGGED) -#if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxSashWindow, wxWindow) IMPLEMENT_DYNAMIC_CLASS(wxSashEvent, wxCommandEvent) @@ -42,30 +47,20 @@ BEGIN_EVENT_TABLE(wxSashWindow, wxWindow) EVT_SIZE(wxSashWindow::OnSize) EVT_MOUSE_EVENTS(wxSashWindow::OnMouseEvent) END_EVENT_TABLE() -#endif -wxSashWindow::wxSashWindow() +bool wxSashWindow::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, + const wxSize& size, long style, const wxString& name) { - m_draggingEdge = wxSASH_NONE; - m_dragMode = wxSASH_DRAG_NONE; - m_oldX = 0; - m_oldY = 0; - m_firstX = 0; - m_firstY = 0; - m_borderSize = 3 ; - m_extraBorderSize = 0; - m_sashCursorWE = NULL; - m_sashCursorNS = NULL; + return wxWindow::Create(parent, id, pos, size, style, name); +} - m_minimumPaneSizeX = 0; - m_minimumPaneSizeY = 0; - m_maximumPaneSizeX = 10000; - m_maximumPaneSizeY = 10000; +wxSashWindow::~wxSashWindow() +{ + delete m_sashCursorWE; + delete m_sashCursorNS; } -wxSashWindow::wxSashWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, - const wxSize& size, long style, const wxString& name) - :wxWindow(parent, id, pos, size, style, name) +void wxSashWindow::Init() { m_draggingEdge = wxSASH_NONE; m_dragMode = wxSASH_DRAG_NONE; @@ -81,43 +76,46 @@ wxSashWindow::wxSashWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos, m_maximumPaneSizeY = 10000; m_sashCursorWE = new wxCursor(wxCURSOR_SIZEWE); m_sashCursorNS = new wxCursor(wxCURSOR_SIZENS); + m_mouseCaptured = FALSE; // Eventually, we'll respond to colour change messages InitColours(); } -wxSashWindow::~wxSashWindow() -{ - delete m_sashCursorWE; - delete m_sashCursorNS; -} - void wxSashWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); -#if 0 - if ( m_borderSize > 0 ) - DrawBorders(dc); -#endif + // if ( m_borderSize > 0 ) + DrawBorders(dc); DrawSashes(dc); } void wxSashWindow::OnMouseEvent(wxMouseEvent& event) { - long x, y; - event.Position(&x, &y); + wxCoord x, y; + event.GetPosition(&x, &y); wxSashEdgePosition sashHit = SashHitTest(x, y); - if (event.LeftDown()) - { + // reset the cursor +#if defined(__WXMOTIF__) || defined(__WXGTK__) + // Not necessary and in fact inhibits proper cursor setting (JACS 8/2000) + //SetCursor(* wxSTANDARD_CURSOR); +#endif +#ifdef __WXMSW__ + SetCursor(wxNullCursor); +#endif + + if (event.LeftDown()) + { + CaptureMouse(); + m_mouseCaptured = TRUE; + if ( sashHit != wxSASH_NONE ) { - CaptureMouse(); - - // Required for X to specify that + // 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. @@ -138,23 +136,36 @@ void wxSashWindow::OnMouseEvent(wxMouseEvent& event) m_draggingEdge = sashHit; m_firstX = x; m_firstY = y; + + if ( (sashHit == wxSASH_LEFT) || (sashHit == wxSASH_RIGHT) ) + { + SetCursor(*m_sashCursorWE); + } + else + { + SetCursor(*m_sashCursorNS); + } } - } + } else if ( event.LeftUp() && m_dragMode == wxSASH_DRAG_LEFT_DOWN ) { // Wasn't a proper drag - ReleaseMouse(); + if (m_mouseCaptured) + ReleaseMouse(); + m_mouseCaptured = FALSE; + wxScreenDC::EndDrawingOnTop(); m_dragMode = wxSASH_DRAG_NONE; m_draggingEdge = wxSASH_NONE; - - SetCursor(*wxSTANDARD_CURSOR); } - else if (event.LeftUp() && m_dragMode == wxSASH_DRAG_DRAGGING) - { + else if (event.LeftUp() && m_dragMode == wxSASH_DRAG_DRAGGING) + { // We can stop dragging now and see what we've got. m_dragMode = wxSASH_DRAG_NONE; - ReleaseMouse(); + if (m_mouseCaptured) + ReleaseMouse(); + m_mouseCaptured = FALSE; + // Erase old tracker DrawSashTracker(m_draggingEdge, m_oldX, m_oldY); @@ -163,100 +174,152 @@ void wxSashWindow::OnMouseEvent(wxMouseEvent& event) wxScreenDC::EndDrawingOnTop(); int w, h; - GetSize(&w, &h); + GetSize(&w, &h); int xp, yp; - GetPosition(&xp, &yp); + GetPosition(&xp, &yp); wxSashEdgePosition edge = m_draggingEdge; m_draggingEdge = wxSASH_NONE; wxRect dragRect; wxSashDragStatus status = wxSASH_STATUS_OK; + + // the new height and width of the window - if -1, it didn't change + int newHeight = -1, + newWidth = -1; + + // NB: x and y may be negative and they're relative to the sash window + // upper left corner, while xp and yp are expressed in the parent + // window system of coordinates, so adjust them! After this + // adjustment, all coordinates are relative to the parent window. + y += yp; + x += xp; + switch (edge) { case wxSASH_TOP: - { - if (y > (yp + h)) + if ( y > yp + h ) + { + // top sash shouldn't get below the bottom one status = wxSASH_STATUS_OUT_OF_RANGE; - int newHeight = (h - y); - newHeight=wxMax(newHeight,m_minimumPaneSizeY); - newHeight=wxMin(newHeight,m_maximumPaneSizeY); - dragRect = wxRect(xp, (yp + h) - newHeight, w, newHeight); + } + else + { + newHeight = h - (y - yp); + } break; - } + case wxSASH_BOTTOM: - { - if (y < 0) + if ( y < yp ) + { + // bottom sash shouldn't get above the top one status = wxSASH_STATUS_OUT_OF_RANGE; - int newHeight = y; - newHeight=wxMax(newHeight,m_minimumPaneSizeY); - newHeight=wxMin(newHeight,m_maximumPaneSizeY); - dragRect = wxRect(xp, yp, w, newHeight); + } + else + { + newHeight = y - yp; + } break; - } + case wxSASH_LEFT: - { - if (x > (xp + w)) + if ( x > xp + w ) + { + // left sash shouldn't get beyond the right one status = wxSASH_STATUS_OUT_OF_RANGE; - int newWidth = (w - x); - newWidth=wxMax(newWidth,m_minimumPaneSizeX); - newWidth=wxMin(newWidth,m_maximumPaneSizeX); - dragRect = wxRect((xp + w) - newWidth, yp, newWidth, h); + } + else + { + newWidth = w - (x - xp); + } break; - } + case wxSASH_RIGHT: - { - if (x < 0) + if ( x < xp ) + { + // and the right sash, finally, shouldn't be beyond the + // left one status = wxSASH_STATUS_OUT_OF_RANGE; - int newWidth = x; - newWidth=wxMax(newWidth,m_minimumPaneSizeX); - newWidth=wxMin(newWidth,m_maximumPaneSizeX); - dragRect = wxRect(xp, yp, newWidth, h); + } + else + { + newWidth = x - xp; + } + break; + + case wxSASH_NONE: + // can this happen at all? break; - } - case wxSASH_NONE: - { - break; - } } + if ( newHeight == -1 ) + { + // didn't change + newHeight = h; + } + else + { + // make sure it's in m_minimumPaneSizeY..m_maximumPaneSizeY range + newHeight = wxMax(newHeight, m_minimumPaneSizeY); + newHeight = wxMin(newHeight, m_maximumPaneSizeY); + } + + if ( newWidth == -1 ) + { + // didn't change + newWidth = w; + } + else + { + // make sure it's in m_minimumPaneSizeY..m_maximumPaneSizeY range + newWidth = wxMax(newWidth, m_minimumPaneSizeX); + newWidth = wxMin(newWidth, m_maximumPaneSizeX); + } + + dragRect = wxRect(x, y, newWidth, newHeight); + wxSashEvent event(GetId(), edge); event.SetEventObject(this); event.SetDragStatus(status); event.SetDragRect(dragRect); GetEventHandler()->ProcessEvent(event); - } - else if (event.Moving() && !event.Dragging()) - { + } + else if ( event.LeftUp() ) + { + if (m_mouseCaptured) + ReleaseMouse(); + m_mouseCaptured = FALSE; + } + else if (event.Moving() && !event.Dragging()) + { // Just change the cursor if required if ( sashHit != wxSASH_NONE ) { - if ( (sashHit == wxSASH_LEFT) || (sashHit == wxSASH_RIGHT) ) - { - SetCursor(*m_sashCursorWE); - } - else - { - SetCursor(*m_sashCursorNS); - } + if ( (sashHit == wxSASH_LEFT) || (sashHit == wxSASH_RIGHT) ) + { + SetCursor(*m_sashCursorWE); + } + else + { + SetCursor(*m_sashCursorNS); + } } else { - SetCursor(*wxSTANDARD_CURSOR); + SetCursor(wxNullCursor); + } + } + else if ( event.Dragging() && + ((m_dragMode == wxSASH_DRAG_DRAGGING) || + (m_dragMode == wxSASH_DRAG_LEFT_DOWN)) ) + { + if ( (m_draggingEdge == wxSASH_LEFT) || (m_draggingEdge == wxSASH_RIGHT) ) + { + SetCursor(*m_sashCursorWE); + } + else + { + SetCursor(*m_sashCursorNS); } - } - else if ( event.Dragging() && - ((m_dragMode == wxSASH_DRAG_DRAGGING) || (m_dragMode == wxSASH_DRAG_LEFT_DOWN)) - ) - { - if ( (m_draggingEdge == wxSASH_LEFT) || (m_draggingEdge == wxSASH_RIGHT) ) - { - SetCursor(*m_sashCursorWE); - } - else - { - SetCursor(*m_sashCursorNS); - } if (m_dragMode == wxSASH_DRAG_LEFT_DOWN) { @@ -265,18 +328,18 @@ void wxSashWindow::OnMouseEvent(wxMouseEvent& event) } else { - if ( m_dragMode == wxSASH_DRAG_DRAGGING ) - { - // Erase old tracker - DrawSashTracker(m_draggingEdge, m_oldX, m_oldY); + if ( m_dragMode == wxSASH_DRAG_DRAGGING ) + { + // Erase old tracker + DrawSashTracker(m_draggingEdge, m_oldX, m_oldY); - // Draw new one - DrawSashTracker(m_draggingEdge, x, y); - } + // Draw new one + DrawSashTracker(m_draggingEdge, x, y); + } } m_oldX = x; m_oldY = y; - } + } else if ( event.LeftDClick() ) { // Nothing @@ -326,7 +389,7 @@ wxSashEdgePosition wxSashWindow::SashHitTest(int x, int y, int WXUNUSED(toleranc } case wxSASH_LEFT: { - if ((x >= GetEdgeMargin(position)) && (x >= 0)) + if ((x <= GetEdgeMargin(position)) && (x >= 0)) return wxSASH_LEFT; break; } @@ -351,7 +414,7 @@ void wxSashWindow::DrawBorders(wxDC& dc) wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID); wxPen hilightPen(m_hilightColour, 1, wxSOLID); - if ( GetWindowStyleFlag() & wxSP_3D ) + if ( GetWindowStyleFlag() & wxSW_3DBORDER ) { dc.SetPen(mediumShadowPen); dc.DrawLine(0, 0, w-1, 0); @@ -370,7 +433,7 @@ void wxSashWindow::DrawBorders(wxDC& dc) dc.DrawLine(w-2, 1, w-2, h-2); // Right hand side dc.DrawLine(1, h-2, w-1, h-2); // Bottom } - else if ( GetWindowStyleFlag() & wxSP_BORDER ) + else if ( GetWindowStyleFlag() & wxSW_BORDER ) { dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetPen(*wxBLACK_PEN); @@ -416,20 +479,20 @@ void wxSashWindow::DrawSash(wxSashEdgePosition edge, wxDC& dc) dc.SetBrush(faceBrush); dc.DrawRectangle(sashPosition, 0, GetEdgeMargin(edge), h); - if (GetWindowStyleFlag() & wxSW_3D) + if (GetWindowStyleFlag() & wxSW_3DSASH) { if (edge == wxSASH_LEFT) { - // Draw a black line on the left to indicate that the + // Draw a dark grey line on the left to indicate that the // sash is raised - dc.SetPen(blackPen); + dc.SetPen(mediumShadowPen); dc.DrawLine(GetEdgeMargin(edge), 0, GetEdgeMargin(edge), h); } else { - // Draw a white line on the right to indicate that the + // Draw a highlight line on the right to indicate that the // sash is raised - dc.SetPen(whitePen); + dc.SetPen(hilightPen); dc.DrawLine(w - GetEdgeMargin(edge), 0, w - GetEdgeMargin(edge), h); } } @@ -446,21 +509,21 @@ void wxSashWindow::DrawSash(wxSashEdgePosition edge, wxDC& dc) dc.SetBrush(faceBrush); dc.DrawRectangle(0, sashPosition, w, GetEdgeMargin(edge)); - if (GetWindowStyleFlag() & wxSW_3D) + if (GetWindowStyleFlag() & wxSW_3DSASH) { if (edge == wxSASH_BOTTOM) { - // Draw a black line on the bottom to indicate that the + // Draw a highlight line on the bottom to indicate that the // sash is raised - dc.SetPen(blackPen); + dc.SetPen(hilightPen); dc.DrawLine(0, h - GetEdgeMargin(edge), w, h - GetEdgeMargin(edge)); } else { - // Draw a white line on the top to indicate that the + // Draw a drak grey line on the top to indicate that the // sash is raised - dc.SetPen(whitePen); - dc.DrawLine(0, GetEdgeMargin(edge), w, GetEdgeMargin(edge)); + dc.SetPen(mediumShadowPen); + dc.DrawLine(1, GetEdgeMargin(edge), w-1, GetEdgeMargin(edge)); } } } @@ -515,7 +578,7 @@ void wxSashWindow::DrawSashTracker(wxSashEdgePosition edge, int x, int y) wxPen sashTrackerPen(*wxBLACK, 2, wxSOLID); - screenDC.SetLogicalFunction(wxXOR); + screenDC.SetLogicalFunction(wxINVERT); screenDC.SetPen(sashTrackerPen); screenDC.SetBrush(*wxTRANSPARENT_BRUSH); @@ -535,7 +598,7 @@ void wxSashWindow::SizeWindows() int cw, ch; GetClientSize(&cw, &ch); - if (GetChildren().Number() > 0) + if (GetChildren().Number() == 1) { wxWindow* child = (wxWindow*) (GetChildren().First()->Data()); @@ -576,6 +639,16 @@ void wxSashWindow::SizeWindows() child->SetSize(x, y, width, height); } + else if (GetChildren().Number() > 1) + { + // Perhaps multiple children are themselves sash windows. + // TODO: this doesn't really work because the subwindows sizes/positions + // must be set to leave a gap for the parent's sash (hit-test and decorations). + // Perhaps we can allow for this within LayoutWindow, testing whether the parent + // is a sash window, and if so, allowing some space for the edges. + wxLayoutAlgorithm layout; + layout.LayoutWindow(this); + } wxClientDC dc(this); DrawBorders(dc); @@ -586,7 +659,7 @@ void wxSashWindow::SizeWindows() void wxSashWindow::InitColours() { // Shadow colours -#if defined(__WIN95__) +#ifndef __WIN16__ m_faceColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE); m_mediumShadowColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW); m_darkShadowColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DDKSHADOW); @@ -610,3 +683,4 @@ void wxSashWindow::SetSashVisible(wxSashEdgePosition edge, bool sash) m_sashes[edge].m_margin = 0; } +#endif // wxUSE_SASH