From a6d7030871f1376e727902c93f5537165a305e08 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Mon, 7 Sep 1998 09:27:34 +0000 Subject: [PATCH 1/1] Added wxSashWindow, wxSashLayoutWindow, wxLayoutAlgorithm classes and sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@702 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/laywin.h | 179 +++++++++++ include/wx/generic/sashwin.h | 214 +++++++++++++ include/wx/laywin.h | 7 + include/wx/sashwin.h | 7 + samples/sashtest/makefile.nt | 51 +++ samples/sashtest/sashtest.cpp | 375 ++++++++++++++++++++++ samples/sashtest/sashtest.h | 79 +++++ samples/sashtest/sashtest.ico | Bin 0 -> 766 bytes samples/sashtest/sashtest.rc | 9 + src/generic/laywin.cpp | 226 +++++++++++++ src/generic/sashwin.cpp | 588 ++++++++++++++++++++++++++++++++++ src/msw/makefile.nt | 12 + 12 files changed, 1747 insertions(+) create mode 100644 include/wx/generic/laywin.h create mode 100644 include/wx/generic/sashwin.h create mode 100644 include/wx/laywin.h create mode 100644 include/wx/sashwin.h create mode 100644 samples/sashtest/makefile.nt create mode 100644 samples/sashtest/sashtest.cpp create mode 100644 samples/sashtest/sashtest.h create mode 100644 samples/sashtest/sashtest.ico create mode 100644 samples/sashtest/sashtest.rc create mode 100644 src/generic/laywin.cpp create mode 100644 src/generic/sashwin.cpp diff --git a/include/wx/generic/laywin.h b/include/wx/generic/laywin.h new file mode 100644 index 0000000000..fcfc87a53d --- /dev/null +++ b/include/wx/generic/laywin.h @@ -0,0 +1,179 @@ +///////////////////////////////////////////////////////////////////////////// +// 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_ diff --git a/include/wx/generic/sashwin.h b/include/wx/generic/sashwin.h new file mode 100644 index 0000000000..c1023929a2 --- /dev/null +++ b/include/wx/generic/sashwin.h @@ -0,0 +1,214 @@ +///////////////////////////////////////////////////////////////////////////// +// 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_ diff --git a/include/wx/laywin.h b/include/wx/laywin.h new file mode 100644 index 0000000000..f3ad27274d --- /dev/null +++ b/include/wx/laywin.h @@ -0,0 +1,7 @@ +#ifndef _WX_LAYWIN_H_BASE_ +#define _WX_LAYWIN_H_BASE_ + +#include "wx/generic/laywin.h" + +#endif + // _WX_LAYWIN_H_BASE_ diff --git a/include/wx/sashwin.h b/include/wx/sashwin.h new file mode 100644 index 0000000000..6b46b6348f --- /dev/null +++ b/include/wx/sashwin.h @@ -0,0 +1,7 @@ +#ifndef _WX_SASHWIN_H_BASE_ +#define _WX_SASHWIN_H_BASE_ + +#include "wx/generic/sashwin.h" + +#endif + // _WX_SASHWIN_H_BASE_ diff --git a/samples/sashtest/makefile.nt b/samples/sashtest/makefile.nt new file mode 100644 index 0000000000..99fa33d92b --- /dev/null +++ b/samples/sashtest/makefile.nt @@ -0,0 +1,51 @@ +# +# 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 + diff --git a/samples/sashtest/sashtest.cpp b/samples/sashtest/sashtest.cpp new file mode 100644 index 0000000000..1542d084eb --- /dev/null +++ b/samples/sashtest/sashtest.cpp @@ -0,0 +1,375 @@ +///////////////////////////////////////////////////////////////////////////// +// 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 +#include + +#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; +} + + diff --git a/samples/sashtest/sashtest.h b/samples/sashtest/sashtest.h new file mode 100644 index 0000000000..ed5fa54197 --- /dev/null +++ b/samples/sashtest/sashtest.h @@ -0,0 +1,79 @@ +///////////////////////////////////////////////////////////////////////////// +// 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 + +// 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 + diff --git a/samples/sashtest/sashtest.ico b/samples/sashtest/sashtest.ico new file mode 100644 index 0000000000000000000000000000000000000000..2dc1bde40cf921731fb2f7c6534054c6fb8d96d1 GIT binary patch literal 766 zcmah{IgY|W5G*e%tq=i3o32BCvHXmAf>Zy(`6TlchZ{QF05Mc`&y2+((WbBJ>H`DN z@#*^mB!3^kH~o>?Q%}?mpR_<=?X?6JSqZ@%EkkNRN{NMRALOiv%14mQONo@Vuu~f2 zR1r@bqoxHgHqbgO7{>y8VLOh4a849H4Zzj{FAJP(g5{I-n)O_*F$%SIE3<<+Nj^dZ zMrsmnqFCH}{&VhK#xlN*^s!HQyVC2cT_ZcBoK?PWy+p6H9A{2%_%Scn3ie-MC5TR` zfM>p7Bv6> literal 0 HcmV?d00001 diff --git a/samples/sashtest/sashtest.rc b/samples/sashtest/sashtest.rc new file mode 100644 index 0000000000..3719f5af81 --- /dev/null +++ b/samples/sashtest/sashtest.rc @@ -0,0 +1,9 @@ +aaaa ICON "sashtest.ico" + +wxSTD_MDIPARENTFRAME ICON "sashtest.ico" +wxSTD_MDICHILDFRAME ICON "sashtest.ico" + +sashtest_icn ICON "sashtest.ico" + +#include "wx/msw/wx.rc" + diff --git a/src/generic/laywin.cpp b/src/generic/laywin.cpp new file mode 100644 index 0000000000..1f2094ed20 --- /dev/null +++ b/src/generic/laywin.cpp @@ -0,0 +1,226 @@ +///////////////////////////////////////////////////////////////////////////// +// 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; +} + diff --git a/src/generic/sashwin.cpp b/src/generic/sashwin.cpp new file mode 100644 index 0000000000..2f53738112 --- /dev/null +++ b/src/generic/sashwin.cpp @@ -0,0 +1,588 @@ +///////////////////////////////////////////////////////////////////////////// +// 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 +#include + +#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; +} + diff --git a/src/msw/makefile.nt b/src/msw/makefile.nt index cb546731b9..a84f84dfdc 100644 --- a/src/msw/makefile.nt +++ b/src/msw/makefile.nt @@ -61,10 +61,12 @@ GENERICOBJS= \ $(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 \ @@ -1074,6 +1076,11 @@ $(GENDIR)/helpxlp.obj: $*.$(SRCSUFF) $(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$@ @@ -1094,6 +1101,11 @@ $(GENDIR)/prntdlgg.obj: $*.$(SRCSUFF) $(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$@ -- 2.47.2