// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
-// Licence: wxWindows license
+// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#include "wx/wx.h"
#endif
+#if wxUSE_SASH
+
#include <math.h>
#include <stdlib.h>
#include "wx/string.h"
#include "wx/dcscreen.h"
#include "wx/sashwin.h"
+#include "wx/laywin.h"
-#if !USE_SHARED_LIBRARY
IMPLEMENT_DYNAMIC_CLASS(wxSashWindow, wxWindow)
IMPLEMENT_DYNAMIC_CLASS(wxSashEvent, wxCommandEvent)
EVT_SIZE(wxSashWindow::OnSize)
EVT_MOUSE_EVENTS(wxSashWindow::OnMouseEvent)
END_EVENT_TABLE()
-#endif
wxSashWindow::wxSashWindow()
{
{
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
+#ifdef __WXMOTIF__
+ SetCursor(* wxSTANDARD_CURSOR);
+#endif
+#ifdef __WXMSW__
+ SetCursor(wxCursor());
+#endif
+
+ if (event.LeftDown())
+ {
if ( sashHit != wxSASH_NONE )
{
- 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.
+ // Find the first frame or dialog and use this to specify
+ // the area to draw on.
+ wxWindow* parent = 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);
+ while (parent && !parent->IsKindOf(CLASSINFO(wxDialog)) &&
+ !parent->IsKindOf(CLASSINFO(wxFrame)))
+ parent = parent->GetParent();
+
+ wxScreenDC::StartDrawingOnTop(parent);
// We don't say we're dragging yet; we leave that
// decision for the Dragging() branch, to ensure
m_firstX = x;
m_firstY = y;
}
- }
+ }
else if ( event.LeftUp() && m_dragMode == wxSASH_DRAG_LEFT_DOWN )
{
// Wasn't a proper drag
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();
+ ReleaseMouse();
// Erase old tracker
DrawSashTracker(m_draggingEdge, m_oldX, m_oldY);
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.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 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(*wxSTANDARD_CURSOR);
+ 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)
{
}
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
}
case wxSASH_LEFT:
{
- if ((x >= GetEdgeMargin(position)) && (x >= 0))
+ if ((x <= GetEdgeMargin(position)) && (x >= 0))
return wxSASH_LEFT;
break;
}
wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID);
wxPen hilightPen(m_hilightColour, 1, wxSOLID);
- if ( GetWindowStyleFlag() & wxSP_3D )
+ if ( GetWindowStyleFlag() & wxSW_3D )
{
dc.SetPen(mediumShadowPen);
dc.DrawLine(0, 0, w-1, 0);
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);
wxPen sashTrackerPen(*wxBLACK, 2, wxSOLID);
- screenDC.SetLogicalFunction(wxXOR);
+ screenDC.SetLogicalFunction(wxINVERT);
screenDC.SetPen(sashTrackerPen);
screenDC.SetBrush(*wxTRANSPARENT_BRUSH);
int cw, ch;
GetClientSize(&cw, &ch);
- if (GetChildren().Number() > 0)
+ if (GetChildren().Number() == 1)
{
wxWindow* child = (wxWindow*) (GetChildren().First()->Data());
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);
m_sashes[edge].m_margin = 0;
}
+#endif // wxUSE_SASH