// 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()
+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 = 0;
- m_maximumPaneSizeY = 0;
+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;
m_extraBorderSize = 0;
m_minimumPaneSizeX = 0;
m_minimumPaneSizeY = 0;
- m_maximumPaneSizeX = 0;
- m_maximumPaneSizeY = 0;
+ m_maximumPaneSizeX = 10000;
+ m_maximumPaneSizeY = 10000;
m_sashCursorWE = new wxCursor(wxCURSOR_SIZEWE);
m_sashCursorNS = new wxCursor(wxCURSOR_SIZENS);
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__)
+ SetCursor(* wxSTANDARD_CURSOR);
+#endif
+#ifdef __WXMSW__
+ SetCursor(wxNullCursor);
+#endif
+
+ if (event.LeftDown())
+ {
+ CaptureMouse();
+
if ( sashHit != wxSASH_NONE )
{
- 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_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
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);
- 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;
- 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);
- 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;
- dragRect = wxRect(xp, yp, newWidth, h);
+ }
+ else
+ {
+ newWidth = x - xp;
+ }
break;
- }
+
+ case wxSASH_NONE:
+ // can this happen at all?
+ 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() )
+ {
+ ReleaseMouse();
+ }
+ 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(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(*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
SizeWindows();
}
-wxSashEdgePosition wxSashWindow::SashHitTest(int x, int y, int tolerance)
+wxSashEdgePosition wxSashWindow::SashHitTest(int x, int y, int WXUNUSED(tolerance))
{
int cx, cy;
GetClientSize(& cx, & cy);
}
case wxSASH_LEFT:
{
- if ((x >= GetEdgeMargin(position)) && (x >= 0))
+ if ((x <= GetEdgeMargin(position)) && (x >= 0))
return wxSASH_LEFT;
break;
}
+ case wxSASH_NONE:
+ {
+ break;
+ }
}
}
}
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);
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);
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);
}
}
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));
}
}
}
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());
+ wxWindow* child = (wxWindow*) (GetChildren().First()->Data());
int x = 0;
int y = 0;
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_hilightColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT);
#else
m_faceColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
- m_mediumShadowColour = *(wxTheColourDatabase->FindColour("GREY", 1, wxSOLID));
+ m_mediumShadowColour = *(wxTheColourDatabase->FindColour("GREY"));
m_darkShadowColour = *(wxTheColourDatabase->FindColour("BLACK"));
m_lightShadowColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
m_hilightColour = *(wxTheColourDatabase->FindColour("WHITE"));
m_sashes[edge].m_margin = 0;
}
+#endif // wxUSE_SASH