--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: laywin.h
+// Purpose: Implements a simple layout algorithm, plus
+// wxSashLayoutWindow which is an example of a window with
+// layout-awareness (via event handlers). This is suited to
+// IDE-style window layout.
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_LAYWIN_H_G_
+#define _WX_LAYWIN_H_G_
+
+#ifdef __GNUG__
+#pragma interface "laywin.h"
+#endif
+
+#include "wx/sashwin.h"
+
+const wxEventType wxEVT_QUERY_LAYOUT_INFO = wxEVT_FIRST + 1500;
+const wxEventType wxEVT_CALCULATE_LAYOUT = wxEVT_FIRST + 1501;
+
+enum wxLayoutOrientation {
+ wxLAYOUT_HORIZONTAL,
+ wxLAYOUT_VERTICAL
+};
+
+enum wxLayoutAlignment {
+ wxLAYOUT_NONE,
+ wxLAYOUT_TOP,
+ wxLAYOUT_LEFT,
+ wxLAYOUT_RIGHT,
+ wxLAYOUT_BOTTOM,
+};
+
+// Not sure this is necessary
+// Tell window which dimension we're sizing on
+#define wxLAYOUT_LENGTH_Y 0x0008
+#define wxLAYOUT_LENGTH_X 0x0000
+
+// Use most recently used length
+#define wxLAYOUT_MRU_LENGTH 0x0010
+
+// Only a query, so don't actually move it.
+#define wxLAYOUT_QUERY 0x0100
+
+/*
+ * This event is used to get information about window alignment,
+ * orientation and size.
+ */
+
+class wxQueryLayoutInfoEvent: public wxEvent
+{
+DECLARE_DYNAMIC_CLASS(wxQueryLayoutInfoEvent)
+public:
+
+ wxQueryLayoutInfoEvent(wxWindowID id = 0)
+ {
+ SetEventType(wxEVT_QUERY_LAYOUT_INFO);
+ m_requestedLength = 0;
+ m_flags = 0;
+ m_alignment = wxLAYOUT_TOP;
+ m_orientation = wxLAYOUT_HORIZONTAL;
+ }
+// Read by the app
+ inline void SetRequestedLength(int length) { m_requestedLength = length; }
+ inline int GetRequestedLength() const { return m_requestedLength; }
+
+ inline void SetFlags(int flags) { m_flags = flags; }
+ inline int GetFlags() const { return m_flags; }
+
+// Set by the app
+ inline void SetSize(const wxSize& size) { m_size = size; }
+ inline wxSize GetSize() const { return m_size; }
+
+ inline void SetOrientation(wxLayoutOrientation orient) { m_orientation = orient; }
+ inline wxLayoutOrientation GetOrientation() const { return m_orientation; }
+
+ inline void SetAlignment(wxLayoutAlignment align) { m_alignment = align; }
+ inline wxLayoutAlignment GetAlignment() const { return m_alignment; }
+protected:
+ int m_flags;
+ int m_requestedLength;
+ wxSize m_size;
+ wxLayoutOrientation m_orientation;
+ wxLayoutAlignment m_alignment;
+
+};
+
+typedef void (wxEvtHandler::*wxQueryLayoutInfoEventFunction)(wxQueryLayoutInfoEvent&);
+
+#define EVT_QUERY_LAYOUT_INFO(func) { wxEVT_QUERY_LAYOUT_INFO, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxQueryLayoutInfoEventFunction) & func, NULL },
+
+/*
+ * This event is used to take a bite out of the available client area.
+ */
+
+class wxCalculateLayoutEvent: public wxEvent
+{
+DECLARE_DYNAMIC_CLASS(wxCalculateLayoutEvent)
+public:
+ wxCalculateLayoutEvent(wxWindowID id = 0)
+ {
+ SetEventType(wxEVT_CALCULATE_LAYOUT);
+ m_flags = 0;
+ }
+// Read by the app
+ inline void SetFlags(int flags) { m_flags = flags; }
+ inline int GetFlags() const { return m_flags; }
+
+// Set by the app
+ inline void SetRect(const wxRect& rect) { m_rect = rect; }
+ inline wxRect GetRect() const { return m_rect; }
+protected:
+ int m_flags;
+ wxRect m_rect;
+};
+
+typedef void (wxEvtHandler::*wxCalculateLayoutEventFunction)(wxCalculateLayoutEvent&);
+
+#define EVT_CALCULATE_LAYOUT(func) { wxEVT_CALCULATE_LAYOUT, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxCalculateLayoutEventFunction) & func, NULL },
+
+// This is window that can remember alignment/orientation, does its own layout,
+// and can provide sashes too. Useful for implementing docked windows with sashes in
+// an IDE-style interface.
+class wxSashLayoutWindow: public wxSashWindow
+{
+ DECLARE_CLASS(wxSashLayoutWindow)
+public:
+ wxSashLayoutWindow(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize, long style = wxSW_3D|wxCLIP_CHILDREN, const wxString& name = "layoutWindow");
+
+// Accessors
+ inline wxLayoutAlignment GetAlignment() const { return m_alignment; };
+ inline wxLayoutOrientation GetOrientation() const { return m_orientation; };
+
+ inline void SetAlignment(wxLayoutAlignment align) { m_alignment = align; };
+ inline void SetOrientation(wxLayoutOrientation orient) { m_orientation = orient; };
+
+ // Give the window default dimensions
+ inline void SetDefaultSize(const wxSize& size) { m_defaultSize = size; }
+
+// Event handlers
+ // Called by layout algorithm to allow window to take a bit out of the
+ // client rectangle, and size itself if not in wxLAYOUT_QUERY mode.
+ void OnCalculateLayout(wxCalculateLayoutEvent& event);
+
+ // Called by layout algorithm to retrieve information about the window.
+ void OnQueryLayoutInfo(wxQueryLayoutInfoEvent& event);
+protected:
+ wxLayoutAlignment m_alignment;
+ wxLayoutOrientation m_orientation;
+ wxSize m_defaultSize;
+
+DECLARE_EVENT_TABLE()
+};
+
+class WXDLLEXPORT wxMDIParentFrame;
+class WXDLLEXPORT wxFrame;
+
+// This class implements the layout algorithm
+class wxLayoutAlgorithm: public wxObject
+{
+public:
+ wxLayoutAlgorithm() {}
+
+ // The MDI client window is sized to whatever's left over.
+ bool LayoutMDIFrame(wxMDIParentFrame* frame);
+
+ // mainWindow is sized to whatever's left over.
+ bool LayoutFrame(wxFrame* frame, wxWindow* mainWindow);
+};
+
+#endif
+ // _WX_LAYWIN_H_G_
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashwin.h
+// Purpose: wxSashWindow implementation. A sash window has an optional
+// sash on each edge, allowing it to be dragged. An event
+// is generated when the sash is released.
+// Author: Julian Smart
+// Modified by:
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_SASHWIN_H_G_
+#define _WX_SASHWIN_H_G_
+
+#ifdef __GNUG__
+#pragma interface "sashwin.h"
+#endif
+
+#include "wx/defs.h"
+#include "wx/window.h"
+#include "wx/string.h"
+
+#define wxSASH_DRAG_NONE 0
+#define wxSASH_DRAG_DRAGGING 1
+#define wxSASH_DRAG_LEFT_DOWN 2
+
+enum wxSashEdgePosition {
+ wxSASH_TOP = 0,
+ wxSASH_RIGHT,
+ wxSASH_BOTTOM,
+ wxSASH_LEFT,
+ wxSASH_NONE = 100
+};
+
+/*
+ * wxSashEdge represents one of the four edges of a window.
+ */
+
+class WXDLLEXPORT wxSashEdge
+{
+public:
+ wxSashEdge() { m_show = FALSE; m_border = FALSE; m_margin = 0; }
+
+ bool m_show; // Is the sash showing?
+ bool m_border; // Do we draw a border?
+ int m_margin; // The margin size
+};
+
+/*
+ * wxSashWindow flags
+ */
+
+#define wxSW_3D 0x0004
+
+/*
+ * wxSashWindow allows any of its edges to have a sash which can be dragged
+ * to resize the window. The actual content window will be created as a child
+ * of wxSashWindow.
+ */
+
+class WXDLLEXPORT wxSashWindow: public wxWindow
+{
+ DECLARE_DYNAMIC_CLASS(wxSashWindow)
+
+public:
+
+////////////////////////////////////////////////////////////////////////////
+// Public API
+
+ // Default constructor
+ wxSashWindow();
+
+ // Normal constructor
+ wxSashWindow(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize, long style = wxSW_3D|wxCLIP_CHILDREN, const wxString& name = "splitter");
+ ~wxSashWindow();
+
+ // Set whether there's a sash in this position
+ void SetSashVisible(wxSashEdgePosition edge, bool sash);
+
+ // Get whether there's a sash in this position
+ inline bool GetSashVisible(wxSashEdgePosition edge) { return m_sashes[edge].m_show; }
+
+ // Set whether there's a border in this position
+ inline void SetSashBorder(wxSashEdgePosition edge, bool border) { m_sashes[edge].m_border = border; }
+
+ // Get whether there's a border in this position
+ inline bool HasBorder(wxSashEdgePosition edge) { return m_sashes[edge].m_border; }
+
+ // Get border size
+ inline int GetEdgeMargin(wxSashEdgePosition edge) { return m_sashes[edge].m_margin; }
+
+ // Sets the default sash border size
+ inline void SetDefaultBorderSize(int width) { m_borderSize = width; }
+
+ // Gets the default sash border size
+ inline int GetDefaultBorderSize() const { return m_borderSize; }
+
+ // Sets the addition border size between child and sash window
+ inline void SetExtraBorderSize(int width) { m_extraBorderSize = width; }
+
+ // Gets the addition border size between child and sash window
+ inline int GetExtraBorderSize() const { return m_extraBorderSize; }
+
+ virtual void SetMinimumSizeX(int min) { m_minimumPaneSizeX = min; }
+ virtual void SetMinimumSizeY(int min) { m_minimumPaneSizeY = min; }
+ virtual int GetMinimumSizeX() const { return m_minimumPaneSizeX; }
+ virtual int GetMinimumSizeY() const { return m_minimumPaneSizeY; }
+
+ virtual void SetMaximumSizeX(int max) { m_maximumPaneSizeX = max; }
+ virtual void SetMaximumSizeY(int max) { m_maximumPaneSizeY = max; }
+ virtual int GetMaximumSizeX() const { return m_maximumPaneSizeX; }
+ virtual int GetMaximumSizeY() const { return m_maximumPaneSizeY; }
+
+////////////////////////////////////////////////////////////////////////////
+// Implementation
+
+ // Paints the border and sash
+ void OnPaint(wxPaintEvent& event);
+
+ // Handles mouse events
+ void OnMouseEvent(wxMouseEvent& ev);
+
+ // Adjusts the panes
+ void OnSize(wxSizeEvent& event);
+
+ // Draws borders
+ void DrawBorders(wxDC& dc);
+
+ // Draws the sashes
+ void DrawSash(wxSashEdgePosition edge, wxDC& dc);
+
+ // Draws the sashes
+ void DrawSashes(wxDC& dc);
+
+ // Draws the sash tracker (for whilst moving the sash)
+ void DrawSashTracker(wxSashEdgePosition edge, int x, int y);
+
+ // Tests for x, y over sash
+ wxSashEdgePosition SashHitTest(int x, int y, int tolerance = 2);
+
+ // Resizes subwindows
+ void SizeWindows();
+
+ // Initialize colours
+ void InitColours();
+
+protected:
+ wxSashEdge m_sashes[4];
+ int m_dragMode;
+ wxSashEdgePosition m_draggingEdge;
+ int m_oldX;
+ int m_oldY;
+ int m_borderSize;
+ int m_extraBorderSize;
+ int m_firstX;
+ int m_firstY;
+ int m_minimumPaneSizeX;
+ int m_minimumPaneSizeY;
+ int m_maximumPaneSizeX;
+ int m_maximumPaneSizeY;
+ wxCursor* m_sashCursorWE;
+ wxCursor* m_sashCursorNS;
+ wxColour m_lightShadowColour;
+ wxColour m_mediumShadowColour;
+ wxColour m_darkShadowColour;
+ wxColour m_hilightColour;
+ wxColour m_faceColour;
+
+DECLARE_EVENT_TABLE()
+};
+
+#define wxEVT_SASH_DRAGGED (wxEVT_FIRST + 1200)
+
+enum wxSashDragStatus
+{
+ wxSASH_STATUS_OK,
+ wxSASH_STATUS_OUT_OF_RANGE
+};
+
+class WXDLLEXPORT wxSashEvent: public wxCommandEvent
+{
+ DECLARE_DYNAMIC_CLASS(wxSashEvent)
+
+ public:
+ inline wxSashEvent(int id = 0, wxSashEdgePosition edge = wxSASH_NONE) {
+ m_eventType = (wxEventType) wxEVT_SASH_DRAGGED; m_id = id; m_edge = edge; }
+
+ inline void SetEdge(wxSashEdgePosition edge) { m_edge = edge; }
+ inline wxSashEdgePosition GetEdge() const { return m_edge; }
+
+ //// The rectangle formed by the drag operation
+ inline void SetDragRect(const wxRect& rect) { m_dragRect = rect; }
+ inline wxRect GetDragRect() const { return m_dragRect; }
+
+ //// Whether the drag caused the rectangle to be reversed (e.g.
+ //// dragging the top below the bottom)
+ inline void SetDragStatus(wxSashDragStatus status) { m_dragStatus = status; }
+ inline wxSashDragStatus GetDragStatus() const { return m_dragStatus; }
+ private:
+ wxSashEdgePosition m_edge;
+ wxRect m_dragRect;
+ wxSashDragStatus m_dragStatus;
+};
+
+typedef void (wxEvtHandler::*wxSashEventFunction)(wxSashEvent&);
+
+#define EVT_SASH_DRAGGED(id, fn) { wxEVT_SASH_DRAGGED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxSashEventFunction) & fn, NULL },
+#define EVT_SASH_DRAGGED_RANGE(id1, id2, fn) { wxEVT_SASH_DRAGGED, id1, id2, (wxObjectEventFunction) (wxEventFunction) (wxSashEventFunction) & fn, NULL },
+
+#endif
+ // _WX_SASHWIN_H_G_
--- /dev/null
+#ifndef _WX_LAYWIN_H_BASE_
+#define _WX_LAYWIN_H_BASE_
+
+#include "wx/generic/laywin.h"
+
+#endif
+ // _WX_LAYWIN_H_BASE_
--- /dev/null
+#ifndef _WX_SASHWIN_H_BASE_
+#define _WX_SASHWIN_H_BASE_
+
+#include "wx/generic/sashwin.h"
+
+#endif
+ // _WX_SASHWIN_H_BASE_
--- /dev/null
+#
+# File: makefile.nt
+# Author: Julian Smart
+# Created: 1993
+# Updated:
+# Copyright: (c) 1993, AIAI, University of Edinburgh
+#
+# "%W% %G%"
+#
+# Makefile : Builds sashtest example (MS VC++).
+# Use FINAL=1 argument to nmake to build final version with no debugging
+# info
+
+# Set WXDIR for your system
+WXDIR = $(WXWIN)
+WXUSINGDLL=0
+
+!include $(WXDIR)\src\ntwxwin.mak
+
+PROGRAM=sashtest
+PROGOBJECTS = $(PROGRAM).obj
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(PROGRAM).exe
+
+$(PROGRAM).exe: $(DUMMYOBJ) $(WXLIB) $(PROGOBJECTS) $(PROGRAM).res
+ $(link) @<<
+-out:$(PROGRAM).exe
+$(LINKFLAGS)
+$(DUMMYOBJ) $(PROGOBJECTS) $(PROGRAM).res
+$(LIBS)
+<<
+
+$(PROGRAM).obj: $(PROGRAM).$(SRCSUFF) $(DUMMYOBJ)
+ $(cc) @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
+<<
+
+$(PROGRAM).res : $(PROGRAM).rc $(WXDIR)\include\wx\msw\wx.rc
+ $(rc) -r /i$(WXDIR)\include -fo$@ $(PROGRAM).rc
+
+
+clean:
+ -erase *.obj
+ -erase *.exe
+ -erase *.res
+ -erase *.map
+ -erase *.sbr
+ -erase *.pdb
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashtest.cpp
+// Purpose: Layout/sash sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart and Markus Holzem
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include <wx/toolbar.h>
+#include <wx/laywin.h>
+
+#include "sashtest.h"
+
+MyFrame *frame = NULL;
+wxList my_children;
+
+IMPLEMENT_APP(MyApp)
+
+// For drawing lines in a canvas
+long xpos = -1;
+long ypos = -1;
+
+int winNumber = 1;
+
+// Initialise this in OnInit, not statically
+bool MyApp::OnInit(void)
+{
+ // Create the main frame window
+
+ frame = new MyFrame(NULL, -1, "Sash Demo", wxPoint(0, 0), wxSize(500, 400),
+ wxDEFAULT_FRAME | wxHSCROLL | wxVSCROLL);
+
+ // Give it an icon (this is ignored in MDI mode: uses resources)
+#ifdef __WXMSW__
+ frame->SetIcon(wxIcon("sashtest_icn"));
+#endif
+#ifdef __X__
+ frame->SetIcon(wxIcon("sashtest.xbm"));
+#endif
+
+ // Make a menubar
+ wxMenu *file_menu = new wxMenu;
+
+ file_menu->Append(SASHTEST_NEW_WINDOW, "&New window");
+ file_menu->Append(SASHTEST_TOGGLE_WINDOW, "&Toggle window");
+ file_menu->Append(SASHTEST_QUIT, "&Exit");
+
+ wxMenu *help_menu = new wxMenu;
+ help_menu->Append(SASHTEST_ABOUT, "&About");
+
+ wxMenuBar *menu_bar = new wxMenuBar;
+
+ menu_bar->Append(file_menu, "&File");
+ menu_bar->Append(help_menu, "&Help");
+
+ // Associate the menu bar with the frame
+ frame->SetMenuBar(menu_bar);
+
+ frame->CreateStatusBar();
+
+ frame->Show(TRUE);
+
+ SetTopWindow(frame);
+
+ return TRUE;
+}
+
+BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
+ EVT_MENU(SASHTEST_ABOUT, MyFrame::OnAbout)
+ EVT_MENU(SASHTEST_NEW_WINDOW, MyFrame::OnNewWindow)
+ EVT_SIZE(MyFrame::OnSize)
+ EVT_MENU(SASHTEST_QUIT, MyFrame::OnQuit)
+ EVT_MENU(SASHTEST_TOGGLE_WINDOW, MyFrame::OnToggleWindow)
+ EVT_SASH_DRAGGED_RANGE(ID_WINDOW_TOP, ID_WINDOW_BOTTOM, MyFrame::OnSashDrag)
+END_EVENT_TABLE()
+
+
+// Define my frame constructor
+MyFrame::MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size,
+ const long style):
+ wxMDIParentFrame(parent, id, title, pos, size, style)
+{
+ // Create some dummy layout windows
+
+ // A window like a toolbar
+ wxSashLayoutWindow* win = new wxSashLayoutWindow(this, ID_WINDOW_TOP, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D);
+ win->SetDefaultSize(wxSize(1000, 30));
+ win->SetOrientation(wxLAYOUT_HORIZONTAL);
+ win->SetAlignment(wxLAYOUT_TOP);
+ win->SetBackgroundColour(wxColour(255, 0, 0));
+ win->SetSashVisible(wxSASH_BOTTOM, TRUE);
+
+ m_topWindow = win;
+
+ // A window like a statusbar
+ win = new wxSashLayoutWindow(this, ID_WINDOW_BOTTOM, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D);
+ win->SetDefaultSize(wxSize(1000, 30));
+ win->SetOrientation(wxLAYOUT_HORIZONTAL);
+ win->SetAlignment(wxLAYOUT_BOTTOM);
+ win->SetBackgroundColour(wxColour(0, 0, 255));
+ win->SetSashVisible(wxSASH_TOP, TRUE);
+
+ m_bottomWindow = win;
+
+ // A window to the left of the client window
+ win = new wxSashLayoutWindow(this, ID_WINDOW_LEFT1, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D);
+ win->SetDefaultSize(wxSize(120, 1000));
+ win->SetOrientation(wxLAYOUT_VERTICAL);
+ win->SetAlignment(wxLAYOUT_LEFT);
+ win->SetBackgroundColour(wxColour(0, 255, 0));
+ win->SetSashVisible(wxSASH_RIGHT, TRUE);
+ win->SetExtraBorderSize(10);
+
+ wxTextCtrl* textWindow = new wxTextCtrl(win, -1, "", wxDefaultPosition, wxDefaultSize,
+ wxTE_MULTILINE|wxSUNKEN_BORDER);
+// wxTE_MULTILINE|wxNO_BORDER);
+ textWindow->SetValue("A help window");
+
+ m_leftWindow1 = win;
+
+ // Another window to the left of the client window
+ win = new wxSashLayoutWindow(this, ID_WINDOW_LEFT2, wxDefaultPosition, wxSize(200, 30), wxNO_BORDER|wxSW_3D);
+ win->SetDefaultSize(wxSize(120, 1000));
+ win->SetOrientation(wxLAYOUT_VERTICAL);
+ win->SetAlignment(wxLAYOUT_LEFT);
+ win->SetBackgroundColour(wxColour(0, 255, 255));
+ win->SetSashVisible(wxSASH_RIGHT, TRUE);
+
+ m_leftWindow2 = win;
+}
+
+void MyFrame::OnQuit(wxCommandEvent& event)
+{
+ Close(TRUE);
+}
+
+void MyFrame::OnAbout(wxCommandEvent& event)
+{
+ (void)wxMessageBox("wxWindows 2.0 Sash Demo\nAuthor: Julian Smart (c) 1998", "About Sash Demo");
+}
+
+void MyFrame::OnToggleWindow(wxCommandEvent& event)
+{
+ if (m_leftWindow1->IsShown())
+ {
+ m_leftWindow1->Show(FALSE);
+ }
+ else
+ {
+ m_leftWindow1->Show(TRUE);
+ }
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+void MyFrame::OnSashDrag(wxSashEvent& event)
+{
+ if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
+ return;
+
+ switch (event.GetId())
+ {
+ case ID_WINDOW_TOP:
+ {
+ m_topWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));
+ break;
+ }
+ case ID_WINDOW_LEFT1:
+ {
+ m_leftWindow1->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));
+ break;
+ }
+ case ID_WINDOW_LEFT2:
+ {
+ m_leftWindow2->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));
+ break;
+ }
+ case ID_WINDOW_BOTTOM:
+ {
+ m_bottomWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));
+ break;
+ }
+ }
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+
+ // Leaves bits of itself behind sometimes
+ GetClientWindow()->Refresh();
+}
+
+void MyFrame::OnNewWindow(wxCommandEvent& event)
+{
+ // Make another frame, containing a canvas
+ MyChild *subframe = new MyChild(frame, "Canvas Frame", wxPoint(10, 10), wxSize(300, 300),
+ wxDEFAULT_FRAME);
+
+ char titleBuf[100];
+ sprintf(titleBuf, "Canvas Frame %d", winNumber);
+ subframe->SetTitle(titleBuf);
+ winNumber ++;
+
+ // Give it an icon (this is ignored in MDI mode: uses resources)
+#ifdef __WXMSW__
+ subframe->SetIcon(wxIcon("sashtest_icn"));
+#endif
+
+ // Give it a status line
+ subframe->CreateStatusBar();
+
+ // Make a menubar
+ wxMenu *file_menu = new wxMenu;
+
+ file_menu->Append(SASHTEST_NEW_WINDOW, "&New window");
+ file_menu->Append(SASHTEST_CHILD_QUIT, "&Close child");
+ file_menu->Append(SASHTEST_QUIT, "&Exit");
+
+ wxMenu *option_menu = new wxMenu;
+
+ // Dummy option
+ option_menu->Append(SASHTEST_REFRESH, "&Refresh picture");
+
+ wxMenu *help_menu = new wxMenu;
+ help_menu->Append(SASHTEST_ABOUT, "&About");
+
+ wxMenuBar *menu_bar = new wxMenuBar;
+
+ menu_bar->Append(file_menu, "&File");
+ menu_bar->Append(option_menu, "&Options");
+ menu_bar->Append(help_menu, "&Help");
+
+ // Associate the menu bar with the frame
+ subframe->SetMenuBar(menu_bar);
+
+ int width, height;
+ subframe->GetClientSize(&width, &height);
+ MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
+ canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
+ subframe->canvas = canvas;
+
+ // Give it scrollbars
+ canvas->SetScrollbars(20, 20, 50, 50);
+
+ subframe->Show(TRUE);
+}
+
+BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
+ EVT_MOUSE_EVENTS(MyCanvas::OnEvent)
+END_EVENT_TABLE()
+
+// Define a constructor for my canvas
+MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size):
+ wxScrolledWindow(parent, -1, pos, size, wxSUNKEN_BORDER)
+{
+}
+
+// Define the repainting behaviour
+void MyCanvas::OnDraw(wxDC& dc)
+{
+ dc.SetFont(*wxSWISS_FONT);
+ dc.SetPen(*wxGREEN_PEN);
+ dc.DrawLine(0, 0, 200, 200);
+ dc.DrawLine(200, 0, 0, 200);
+
+ dc.SetBrush(*wxCYAN_BRUSH);
+ dc.SetPen(*wxRED_PEN);
+ dc.DrawRectangle(100, 100, 100, 50);
+ dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
+
+ dc.DrawEllipse(250, 250, 100, 50);
+ dc.DrawSpline(50, 200, 50, 100, 200, 10);
+ dc.DrawLine(50, 230, 200, 230);
+ dc.DrawText("This is a test string", 50, 230);
+
+ wxPoint points[3];
+ points[0].x = 200; points[0].y = 300;
+ points[1].x = 100; points[1].y = 400;
+ points[2].x = 300; points[2].y = 400;
+
+ dc.DrawPolygon(3, points);
+}
+
+// This implements a tiny doodling program! Drag the mouse using
+// the left button.
+void MyCanvas::OnEvent(wxMouseEvent& event)
+{
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ wxPoint pt(event.GetLogicalPosition(dc));
+
+ if (xpos > -1 && ypos > -1 && event.Dragging())
+ {
+ dc.SetPen(*wxBLACK_PEN);
+ dc.DrawLine(xpos, ypos, pt.x, pt.y);
+ }
+ xpos = pt.x;
+ ypos = pt.y;
+}
+
+// Define the behaviour for the frame closing
+// - must delete all frames except for the main one.
+bool MyFrame::OnClose(void)
+{
+ // Must delete children
+ wxNode *node = my_children.First();
+ while (node)
+ {
+ MyChild *child = (MyChild *)node->Data();
+ wxNode *next = node->Next();
+ child->OnClose();
+ delete child;
+ node = next;
+ }
+ return TRUE;
+}
+
+void MyFrame::OnSize(wxSizeEvent& event)
+{
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+// Note that SASHTEST_NEW_WINDOW and SASHTEST_ABOUT commands get passed
+// to the parent window for processing, so no need to
+// duplicate event handlers here.
+
+BEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame)
+ EVT_MENU(SASHTEST_CHILD_QUIT, MyChild::OnQuit)
+END_EVENT_TABLE()
+
+MyChild::MyChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size,
+const long style):
+ wxMDIChildFrame(parent, -1, title, pos, size, style)
+{
+ canvas = NULL;
+ my_children.Append(this);
+}
+
+MyChild::~MyChild(void)
+{
+ my_children.DeleteObject(this);
+}
+
+void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+ Close(TRUE);
+}
+
+void MyChild::OnActivate(wxActivateEvent& event)
+{
+ if (event.GetActive() && canvas)
+ canvas->SetFocus();
+}
+
+bool MyChild::OnClose(void)
+{
+ return TRUE;
+}
+
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashtest.h
+// Purpose: Layout window/sash sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#include <wx/toolbar.h>
+
+// Define a new application
+class MyApp: public wxApp
+{
+ public:
+ bool OnInit(void);
+};
+
+class MyCanvas: public wxScrolledWindow
+{
+ public:
+ MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
+ virtual void OnDraw(wxDC& dc);
+ void OnEvent(wxMouseEvent& event);
+
+ DECLARE_EVENT_TABLE()
+};
+
+// Define a new frame
+class MyFrame: public wxMDIParentFrame
+{
+ public:
+
+ MyFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
+
+ bool OnClose(void);
+ void OnSize(wxSizeEvent& event);
+ void OnAbout(wxCommandEvent& event);
+ void OnNewWindow(wxCommandEvent& event);
+ void OnQuit(wxCommandEvent& event);
+ void OnToggleWindow(wxCommandEvent& event);
+ void OnSashDrag(wxSashEvent& event);
+
+protected:
+ wxSashLayoutWindow* m_topWindow;
+ wxSashLayoutWindow* m_leftWindow1;
+ wxSashLayoutWindow* m_leftWindow2;
+ wxSashLayoutWindow* m_bottomWindow;
+
+DECLARE_EVENT_TABLE()
+};
+
+class MyChild: public wxMDIChildFrame
+{
+ public:
+ MyCanvas *canvas;
+ MyChild(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
+ ~MyChild(void);
+ bool OnClose(void);
+ void OnActivate(wxActivateEvent& event);
+ void OnQuit(wxCommandEvent& event);
+
+DECLARE_EVENT_TABLE()
+};
+
+#define SASHTEST_QUIT 1
+#define SASHTEST_NEW_WINDOW 2
+#define SASHTEST_REFRESH 3
+#define SASHTEST_CHILD_QUIT 4
+#define SASHTEST_ABOUT 5
+#define SASHTEST_TOGGLE_WINDOW 6
+
+#define ID_WINDOW_TOP 100
+#define ID_WINDOW_LEFT1 101
+#define ID_WINDOW_LEFT2 102
+#define ID_WINDOW_BOTTOM 103
+
--- /dev/null
+aaaa ICON "sashtest.ico"
+
+wxSTD_MDIPARENTFRAME ICON "sashtest.ico"
+wxSTD_MDICHILDFRAME ICON "sashtest.ico"
+
+sashtest_icn ICON "sashtest.ico"
+
+#include "wx/msw/wx.rc"
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: laywin.cpp
+// Purpose: Implements a simple layout algorithm, plus
+// wxSashLayoutWindow which is an example of a window with
+// layout-awareness (via event handlers). This is suited to
+// IDE-style window layout.
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include "wx/laywin.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxQueryLayoutInfoEvent, wxEvent)
+IMPLEMENT_DYNAMIC_CLASS(wxCalculateLayoutEvent, wxEvent)
+
+IMPLEMENT_CLASS(wxSashLayoutWindow, wxSashWindow)
+
+BEGIN_EVENT_TABLE(wxSashLayoutWindow, wxSashWindow)
+ EVT_CALCULATE_LAYOUT(wxSashLayoutWindow::OnCalculateLayout)
+ EVT_QUERY_LAYOUT_INFO(wxSashLayoutWindow::OnQueryLayoutInfo)
+END_EVENT_TABLE()
+
+wxSashLayoutWindow::wxSashLayoutWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos,
+ const wxSize& size, long style, const wxString& name):
+ wxSashWindow(parent, id, pos, size, style, name)
+{
+ m_orientation = wxLAYOUT_HORIZONTAL;
+ m_alignment = wxLAYOUT_TOP;
+}
+
+// These are the functions that wxWin will call to ascertain the window
+// dimensions.
+void wxSashLayoutWindow::OnQueryLayoutInfo(wxQueryLayoutInfoEvent& event)
+{
+ int flags = event.GetFlags();
+ int requestedLength = event.GetRequestedLength();
+
+ // This code won't be in the final thing, it's just so we don't have to give it
+ // real windows: mock up some dimensions.
+
+ event.SetOrientation(m_orientation);
+ event.SetAlignment(m_alignment);
+
+ if (m_orientation == wxLAYOUT_HORIZONTAL)
+ event.SetSize(wxSize(requestedLength, m_defaultSize.y));
+ else
+ event.SetSize(wxSize(m_defaultSize.x, requestedLength));
+}
+
+// Called by parent to allow window to take a bit out of the
+// client rectangle, and size itself if not in wxLAYOUT_QUERY mode.
+// Will eventually be an event.
+
+void wxSashLayoutWindow::OnCalculateLayout(wxCalculateLayoutEvent& event)
+{
+ wxRect clientSize(event.GetRect());
+
+ int flags = event.GetFlags();
+
+ if (!IsShown())
+ return;
+
+ // Let's assume that all windows stretch the full extent of the window in
+ // the direction of that window orientation. This will work for non-docking toolbars,
+ // and the status bar. Note that the windows have to have been created in a certain
+ // order to work, else you might get a left-aligned window going to the bottom
+ // of the window, and the status bar appearing to the right of it. The
+ // status bar would have to be created after or before the toolbar(s).
+
+ wxRect thisRect;
+
+ // Try to stretch
+ int length = (GetOrientation() == wxLAYOUT_HORIZONTAL) ? clientSize.width : clientSize.height;
+ wxLayoutOrientation orient = GetOrientation();
+
+ // We assume that a window that says it's horizontal, wants to be stretched in that
+ // direction. Is this distinction too fine? Do we assume that any horizontal
+ // window needs to be stretched in that direction? Possibly.
+ int whichDimension = (GetOrientation() == wxLAYOUT_HORIZONTAL) ? wxLAYOUT_LENGTH_X : wxLAYOUT_LENGTH_Y;
+
+ wxQueryLayoutInfoEvent infoEvent(GetId());
+ infoEvent.SetEventObject(this);
+ infoEvent.SetRequestedLength(length);
+ infoEvent.SetFlags(orient | whichDimension);
+
+ if (!GetEventHandler()->ProcessEvent(infoEvent))
+ return;
+
+ wxSize sz = infoEvent.GetSize();
+
+ if (sz.x == 0 && sz.y == 0) // Assume it's invisible
+ return;
+
+ // Now we know the size it wants to be. We wish to decide where to place it, i.e.
+ // how it's aligned.
+ switch (GetAlignment())
+ {
+ case wxLAYOUT_TOP:
+ {
+ thisRect.x = clientSize.x; thisRect.y = clientSize.y;
+ thisRect.width = sz.x; thisRect.height = sz.y;
+ clientSize.y += thisRect.height;
+ clientSize.height -= thisRect.height;
+ break;
+ }
+ case wxLAYOUT_LEFT:
+ {
+ thisRect.x = clientSize.x; thisRect.y = clientSize.y;
+ thisRect.width = sz.x; thisRect.height = sz.y;
+ clientSize.x += thisRect.width;
+ clientSize.width -= thisRect.width;
+ break;
+ }
+ case wxLAYOUT_RIGHT:
+ {
+ thisRect.x = clientSize.x + (clientSize.width - sz.x); thisRect.y = clientSize.y;
+ thisRect.width = sz.x; thisRect.height = sz.y;
+ clientSize.width -= thisRect.width;
+ break;
+ }
+ case wxLAYOUT_BOTTOM:
+ {
+ thisRect.x = clientSize.x; thisRect.y = clientSize.y + (clientSize.height - sz.y);
+ thisRect.width = sz.x; thisRect.height = sz.y;
+ clientSize.height -= thisRect.height;
+ break;
+ }
+ }
+
+ if ((flags & wxLAYOUT_QUERY) == 0)
+ {
+ // If not in query mode, resize the window.
+ // TODO: add wxRect& form to wxWindow::SetSize
+ SetSize(thisRect.x, thisRect.y, thisRect.width, thisRect.height);
+ }
+
+ event.SetRect(clientSize);
+}
+
+/*
+ * wxLayoutAlgorithm
+ */
+
+// Lays out windows for an MDI frame. The MDI client area gets what's left
+// over.
+bool wxLayoutAlgorithm::LayoutMDIFrame(wxMDIParentFrame* frame)
+{
+ int cw, ch;
+ frame->GetClientSize(& cw, & ch);
+
+ wxRect rect(0, 0, cw, ch);
+
+ wxCalculateLayoutEvent event;
+ event.SetRect(rect);
+
+ wxNode* node = frame->GetChildren()->First();
+ while (node)
+ {
+ wxWindow* win = (wxWindow*) node->Data();
+
+ event.SetId(win->GetId());
+ event.SetEventObject(win);
+ event.SetFlags(0); // ??
+
+ win->GetEventHandler()->ProcessEvent(event);
+
+ node = node->Next();
+ }
+
+ wxWindow* clientWindow = frame->GetClientWindow();
+
+ rect = event.GetRect();
+
+ clientWindow->SetSize(rect.x, rect.y, rect.width, rect.height);
+
+ return TRUE;
+}
+
+// Layout algorithm for normal frame. mainWindow gets what's left over.
+bool wxLayoutAlgorithm::LayoutFrame(wxFrame* frame, wxWindow* mainWindow)
+{
+ int cw, ch;
+ frame->GetClientSize(& cw, & ch);
+
+ wxRect rect(0, 0, cw, ch);
+
+ wxCalculateLayoutEvent event;
+ event.SetRect(rect);
+
+ wxNode* node = frame->GetChildren()->First();
+ while (node)
+ {
+ wxWindow* win = (wxWindow*) node->Data();
+
+ event.SetId(win->GetId());
+ event.SetEventObject(win);
+ event.SetFlags(0); // ??
+
+ win->GetEventHandler()->ProcessEvent(event);
+
+ node = node->Next();
+ }
+
+ rect = event.GetRect();
+
+ mainWindow->SetSize(rect.x, rect.y, rect.width, rect.height);
+
+ return TRUE;
+}
+
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashwin.cpp
+// Purpose: wxSashWindow implementation. A sash window has an optional
+// sash on each edge, allowing it to be dragged. An event
+// is generated when the sash is released.
+// Author: Julian Smart
+// Modified by:
+// Created: 01/02/97
+// RCS-ID: $Id$
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "sashwin.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "wx/string.h"
+#include "wx/dcscreen.h"
+#include "wx/sashwin.h"
+
+#if !USE_SHARED_LIBRARY
+IMPLEMENT_DYNAMIC_CLASS(wxSashWindow, wxWindow)
+IMPLEMENT_DYNAMIC_CLASS(wxSashEvent, wxCommandEvent)
+
+BEGIN_EVENT_TABLE(wxSashWindow, wxWindow)
+ EVT_PAINT(wxSashWindow::OnPaint)
+ EVT_SIZE(wxSashWindow::OnSize)
+ EVT_MOUSE_EVENTS(wxSashWindow::OnMouseEvent)
+END_EVENT_TABLE()
+#endif
+
+wxSashWindow::wxSashWindow()
+{
+ 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;
+
+ m_minimumPaneSizeX = 0;
+ m_minimumPaneSizeY = 0;
+ m_maximumPaneSizeX = 0;
+ m_maximumPaneSizeY = 0;
+}
+
+wxSashWindow::wxSashWindow(wxWindow *parent, wxWindowID id, const wxPoint& pos,
+ const wxSize& size, long style, const wxString& name)
+ :wxWindow(parent, id, pos, size, style, 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_minimumPaneSizeX = 0;
+ m_minimumPaneSizeY = 0;
+ m_maximumPaneSizeX = 0;
+ m_maximumPaneSizeY = 0;
+ m_sashCursorWE = new wxCursor(wxCURSOR_SIZEWE);
+ m_sashCursorNS = new wxCursor(wxCURSOR_SIZENS);
+
+ // 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
+
+ DrawSashes(dc);
+}
+
+void wxSashWindow::OnMouseEvent(wxMouseEvent& event)
+{
+ long x, y;
+ event.Position(&x, &y);
+
+ wxSashEdgePosition sashHit = SashHitTest(x, y);
+
+ if (event.LeftDown())
+ {
+ 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.
+ 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 = wxSASH_DRAG_LEFT_DOWN;
+ m_draggingEdge = sashHit;
+ m_firstX = x;
+ m_firstY = y;
+ }
+ }
+ else if ( event.LeftUp() && m_dragMode == wxSASH_DRAG_LEFT_DOWN )
+ {
+ // Wasn't a proper drag
+ ReleaseMouse();
+ wxScreenDC::EndDrawingOnTop();
+ m_dragMode = wxSASH_DRAG_NONE;
+ m_draggingEdge = wxSASH_NONE;
+
+ SetCursor(*wxSTANDARD_CURSOR);
+ }
+ 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();
+ // Erase old tracker
+ DrawSashTracker(m_draggingEdge, m_oldX, m_oldY);
+
+ // End drawing on top (frees the window used for drawing
+ // over the screen)
+ wxScreenDC::EndDrawingOnTop();
+
+ int w, h;
+ GetSize(&w, &h);
+ int xp, yp;
+ GetPosition(&xp, &yp);
+
+ wxSashEdgePosition edge = m_draggingEdge;
+ m_draggingEdge = wxSASH_NONE;
+
+ wxRect dragRect;
+ wxSashDragStatus status = wxSASH_STATUS_OK;
+ switch (edge)
+ {
+ case wxSASH_TOP:
+ {
+ if (y > (yp + h))
+ status = wxSASH_STATUS_OUT_OF_RANGE;
+ int newHeight = (h - y);
+ dragRect = wxRect(xp, (yp + h) - newHeight, w, newHeight);
+ break;
+ }
+ case wxSASH_BOTTOM:
+ {
+ if (y < 0)
+ status = wxSASH_STATUS_OUT_OF_RANGE;
+ int newHeight = y;
+ dragRect = wxRect(xp, yp, w, newHeight);
+ break;
+ }
+ case wxSASH_LEFT:
+ {
+ if (x > (xp + w))
+ status = wxSASH_STATUS_OUT_OF_RANGE;
+ int newWidth = (w - x);
+ dragRect = wxRect((xp + w) - newWidth, yp, newWidth, h);
+ break;
+ }
+ case wxSASH_RIGHT:
+ {
+ if (x < 0)
+ status = wxSASH_STATUS_OUT_OF_RANGE;
+ int newWidth = x;
+ dragRect = wxRect(xp, yp, newWidth, h);
+ break;
+ }
+ }
+
+ wxSashEvent event(GetId(), edge);
+ event.SetEventObject(this);
+ event.SetDragStatus(status);
+ event.SetDragRect(dragRect);
+ GetEventHandler()->ProcessEvent(event);
+ }
+ 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);
+ }
+ }
+ else
+ {
+ SetCursor(*wxSTANDARD_CURSOR);
+ }
+ }
+ 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)
+ {
+ m_dragMode = wxSASH_DRAG_DRAGGING;
+ DrawSashTracker(m_draggingEdge, x, y);
+ }
+ else
+ {
+ if ( m_dragMode == wxSASH_DRAG_DRAGGING )
+ {
+ // Erase old tracker
+ DrawSashTracker(m_draggingEdge, m_oldX, m_oldY);
+
+ // Draw new one
+ DrawSashTracker(m_draggingEdge, x, y);
+ }
+ }
+ m_oldX = x;
+ m_oldY = y;
+ }
+ else if ( event.LeftDClick() )
+ {
+ // Nothing
+ }
+ else
+ {
+ }
+}
+
+void wxSashWindow::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+ SizeWindows();
+}
+
+wxSashEdgePosition wxSashWindow::SashHitTest(int x, int y, int tolerance)
+{
+ int cx, cy;
+ GetClientSize(& cx, & cy);
+
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ wxSashEdge& edge = m_sashes[i];
+ wxSashEdgePosition position = (wxSashEdgePosition) i ;
+
+ if (edge.m_show)
+ {
+ switch (position)
+ {
+ case wxSASH_TOP:
+ {
+ if (y >= 0 && y <= GetEdgeMargin(position))
+ return wxSASH_TOP;
+ break;
+ }
+ case wxSASH_RIGHT:
+ {
+ if ((x >= cx - GetEdgeMargin(position)) && (x <= cx))
+ return wxSASH_RIGHT;
+ break;
+ }
+ case wxSASH_BOTTOM:
+ {
+ if ((y >= cy - GetEdgeMargin(position)) && (y <= cy))
+ return wxSASH_BOTTOM;
+ break;
+ }
+ case wxSASH_LEFT:
+ {
+ if ((x >= GetEdgeMargin(position)) && (x >= 0))
+ return wxSASH_LEFT;
+ break;
+ }
+ }
+ }
+ }
+ return wxSASH_NONE;
+}
+
+// Draw 3D effect borders
+void wxSashWindow::DrawBorders(wxDC& dc)
+{
+ int w, h;
+ GetClientSize(&w, &h);
+
+ wxPen mediumShadowPen(m_mediumShadowColour, 1, wxSOLID);
+ wxPen darkShadowPen(m_darkShadowColour, 1, wxSOLID);
+ wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID);
+ wxPen hilightPen(m_hilightColour, 1, wxSOLID);
+
+ if ( GetWindowStyleFlag() & wxSP_3D )
+ {
+ dc.SetPen(mediumShadowPen);
+ dc.DrawLine(0, 0, w-1, 0);
+ dc.DrawLine(0, 0, 0, h - 1);
+
+ dc.SetPen(darkShadowPen);
+ dc.DrawLine(1, 1, w-2, 1);
+ dc.DrawLine(1, 1, 1, h-2);
+
+ dc.SetPen(hilightPen);
+ dc.DrawLine(0, h-1, w-1, h-1);
+ dc.DrawLine(w-1, 0, w-1, h); // Surely the maximum y pos. should be h - 1.
+ /// Anyway, h is required for MSW.
+
+ dc.SetPen(lightShadowPen);
+ 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 )
+ {
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ dc.SetPen(*wxBLACK_PEN);
+ dc.DrawRectangle(0, 0, w-1, h-1);
+ }
+
+ dc.SetPen(wxNullPen);
+ dc.SetBrush(wxNullBrush);
+}
+
+void wxSashWindow::DrawSashes(wxDC& dc)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ if (m_sashes[i].m_show)
+ DrawSash((wxSashEdgePosition) i, dc);
+}
+
+// Draw the sash
+void wxSashWindow::DrawSash(wxSashEdgePosition edge, wxDC& dc)
+{
+ int w, h;
+ GetClientSize(&w, &h);
+
+ wxPen facePen(m_faceColour, 1, wxSOLID);
+ wxBrush faceBrush(m_faceColour, wxSOLID);
+ wxPen mediumShadowPen(m_mediumShadowColour, 1, wxSOLID);
+ wxPen darkShadowPen(m_darkShadowColour, 1, wxSOLID);
+ wxPen lightShadowPen(m_lightShadowColour, 1, wxSOLID);
+ wxPen hilightPen(m_hilightColour, 1, wxSOLID);
+ wxPen blackPen(wxColour(0, 0, 0), 1, wxSOLID);
+ wxPen whitePen(wxColour(255, 255, 255), 1, wxSOLID);
+
+ if ( edge == wxSASH_LEFT || edge == wxSASH_RIGHT )
+ {
+ int sashPosition = 0;
+ if (edge == wxSASH_LEFT)
+ sashPosition = 0;
+ else
+ sashPosition = w - GetEdgeMargin(edge);
+
+ dc.SetPen(facePen);
+ dc.SetBrush(faceBrush);
+ dc.DrawRectangle(sashPosition, 0, GetEdgeMargin(edge), h);
+
+ if (GetWindowStyleFlag() & wxSW_3D)
+ {
+ if (edge == wxSASH_LEFT)
+ {
+ // Draw a black line on the left to indicate that the
+ // sash is raised
+ dc.SetPen(blackPen);
+ dc.DrawLine(GetEdgeMargin(edge), 0, GetEdgeMargin(edge), h);
+ }
+ else
+ {
+ // Draw a white line on the right to indicate that the
+ // sash is raised
+ dc.SetPen(whitePen);
+ dc.DrawLine(w - GetEdgeMargin(edge), 0, w - GetEdgeMargin(edge), h);
+ }
+ }
+ }
+ else // top or bottom
+ {
+ int sashPosition = 0;
+ if (edge == wxSASH_TOP)
+ sashPosition = 0;
+ else
+ sashPosition = h - GetEdgeMargin(edge);
+
+ dc.SetPen(facePen);
+ dc.SetBrush(faceBrush);
+ dc.DrawRectangle(0, sashPosition, w, GetEdgeMargin(edge));
+
+ if (GetWindowStyleFlag() & wxSW_3D)
+ {
+ if (edge == wxSASH_BOTTOM)
+ {
+ // Draw a black line on the bottom to indicate that the
+ // sash is raised
+ dc.SetPen(blackPen);
+ dc.DrawLine(0, h - GetEdgeMargin(edge), w, h - GetEdgeMargin(edge));
+ }
+ else
+ {
+ // Draw a white line on the top to indicate that the
+ // sash is raised
+ dc.SetPen(whitePen);
+ dc.DrawLine(0, GetEdgeMargin(edge), w, GetEdgeMargin(edge));
+ }
+ }
+ }
+
+ dc.SetPen(wxNullPen);
+ dc.SetBrush(wxNullBrush);
+}
+
+// Draw the sash tracker (for whilst moving the sash)
+void wxSashWindow::DrawSashTracker(wxSashEdgePosition edge, int x, int y)
+{
+ int w, h;
+ GetClientSize(&w, &h);
+
+ wxScreenDC screenDC;
+ int x1, y1;
+ int x2, y2;
+
+ if ( edge == wxSASH_LEFT || edge == wxSASH_RIGHT )
+ {
+ x1 = x; y1 = 2;
+ x2 = x; y2 = h-2;
+
+ if ( (edge == wxSASH_LEFT) && (x1 > w) )
+ {
+ x1 = w; x2 = w;
+ }
+ else if ( (edge == wxSASH_RIGHT) && (x1 < 0) )
+ {
+ x1 = 0; x2 = 0;
+ }
+ }
+ else
+ {
+ x1 = 2; y1 = y;
+ x2 = w-2; y2 = y;
+
+ if ( (edge == wxSASH_TOP) && (y1 > h) )
+ {
+ y1 = h;
+ y2 = h;
+ }
+ else if ( (edge == wxSASH_BOTTOM) && (y1 < 0) )
+ {
+ y1 = 0;
+ y2 = 0;
+ }
+ }
+
+ ClientToScreen(&x1, &y1);
+ ClientToScreen(&x2, &y2);
+
+ wxPen sashTrackerPen(*wxBLACK, 2, wxSOLID);
+
+ screenDC.SetLogicalFunction(wxXOR);
+ screenDC.SetPen(sashTrackerPen);
+ screenDC.SetBrush(*wxTRANSPARENT_BRUSH);
+
+ screenDC.DrawLine(x1, y1, x2, y2);
+
+ screenDC.SetLogicalFunction(wxCOPY);
+
+ screenDC.SetPen(wxNullPen);
+ screenDC.SetBrush(wxNullBrush);
+}
+
+// Position and size subwindows.
+// Note that the border size applies to each subwindow, not
+// including the edges next to the sash.
+void wxSashWindow::SizeWindows()
+{
+ int cw, ch;
+ GetClientSize(&cw, &ch);
+
+ if (GetChildren()->Number() > 0)
+ {
+ wxWindow* child = (wxWindow*) (GetChildren()->First()->Data());
+
+ int x = 0;
+ int y = 0;
+ int width = cw;
+ int height = ch;
+
+ // Top
+ if (m_sashes[0].m_show)
+ {
+ y = m_borderSize;
+ height -= m_borderSize;
+ }
+ y += m_extraBorderSize;
+
+ // Left
+ if (m_sashes[3].m_show)
+ {
+ x = m_borderSize;
+ width -= m_borderSize;
+ }
+ x += m_extraBorderSize;
+
+ // Right
+ if (m_sashes[1].m_show)
+ {
+ width -= m_borderSize;
+ }
+ width -= 2*m_extraBorderSize;
+
+ // Bottom
+ if (m_sashes[2].m_show)
+ {
+ height -= m_borderSize;
+ }
+ height -= 2*m_extraBorderSize;
+
+ child->SetSize(x, y, width, height);
+ }
+
+ wxClientDC dc(this);
+ DrawBorders(dc);
+ DrawSashes(dc);
+}
+
+// Initialize colours
+void wxSashWindow::InitColours()
+{
+ // Shadow colours
+#if defined(__WIN95__)
+ m_faceColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
+ m_mediumShadowColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW);
+ m_darkShadowColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DDKSHADOW);
+ m_lightShadowColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT);
+ m_hilightColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHILIGHT);
+#else
+ m_faceColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
+ m_mediumShadowColour = *(wxTheColourDatabase->FindColour("GREY", 1, wxSOLID));
+ m_darkShadowColour = *(wxTheColourDatabase->FindColour("BLACK"));
+ m_lightShadowColour = *(wxTheColourDatabase->FindColour("LIGHT GREY"));
+ m_hilightColour = *(wxTheColourDatabase->FindColour("WHITE"));
+#endif
+}
+
+void wxSashWindow::SetSashVisible(wxSashEdgePosition edge, bool sash)
+{
+ m_sashes[edge].m_show = sash;
+ if (sash)
+ m_sashes[edge].m_margin = m_borderSize;
+ else
+ m_sashes[edge].m_margin = 0;
+}
+
$(GENDIR)\fontdlgg.obj \
$(GENDIR)\gridg.obj \
$(GENDIR)\helpxlp.obj \
+ $(GENDIR)\laywin.obj \
$(GENDIR)\msgdlgg.obj \
$(GENDIR)\panelg.obj \
$(GENDIR)\printps.obj \
$(GENDIR)\prntdlgg.obj \
+ $(GENDIR)\sashwin.obj \
$(GENDIR)\scrolwin.obj \
$(GENDIR)\splitter.obj \
$(GENDIR)\statusbr.obj \
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@
<<
+$(GENDIR)/laywin.obj: $*.$(SRCSUFF)
+ cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@
+<<
+
$(GENDIR)/msgdlgg.obj: $*.$(SRCSUFF)
cl @<<
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@
<<
+$(GENDIR)/sashwin.obj: $*.$(SRCSUFF)
+ cl @<<
+$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@
+<<
+
$(GENDIR)/scrolwin.obj: $*.$(SRCSUFF)
cl @<<
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF) /Fo$@