From: Vadim Zeitlin Date: Mon, 10 Oct 2005 18:24:27 +0000 (+0000) Subject: refactored wxGTK scrolling: it has now fully-functioning wxScrollHelper and a lot... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/d32e78bd428286561c0db32afda4dea7e262cb84?ds=inline refactored wxGTK scrolling: it has now fully-functioning wxScrollHelper and a lot of duplicate code was removed git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35875 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/scrolwin.h b/include/wx/generic/scrolwin.h index 5586fd5a3c..de52bde70e 100644 --- a/include/wx/generic/scrolwin.h +++ b/include/wx/generic/scrolwin.h @@ -19,72 +19,9 @@ #include "wx/window.h" #include "wx/panel.h" -extern WXDLLEXPORT_DATA(const wxChar*) wxPanelNameStr; - -// default scrolled window style -#ifndef wxScrolledWindowStyle - #define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) -#endif - // ---------------------------------------------------------------------------- // wxGenericScrolledWindow // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxGenericScrolledWindow : public wxPanel, - public wxScrollHelper -{ -public: - wxGenericScrolledWindow() : wxScrollHelper(this) { } - wxGenericScrolledWindow(wxWindow *parent, - wxWindowID winid = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr) - : wxScrollHelper(this) - { - Create(parent, winid, pos, size, style, name); - } - - virtual ~wxGenericScrolledWindow(); - - bool Create(wxWindow *parent, - wxWindowID winid, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr); - - virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } - - // lay out the window and its children - virtual bool Layout(); - - virtual void DoSetVirtualSize(int x, int y); - - // wxWindow's GetBestVirtualSize returns the actual window size, - // whereas we want to return the virtual size - virtual wxSize GetBestVirtualSize() const; - - // Return the size best suited for the current window - // (this isn't a virtual size, this is a sensible size for the window) - virtual wxSize DoGetBestSize() const; - -protected: - // this is needed for wxEVT_PAINT processing hack described in - // wxScrollHelperEvtHandler::ProcessEvent() - void OnPaint(wxPaintEvent& event); - - // we need to return a special WM_GETDLGCODE value to process just the - // arrows but let the other navigation characters through -#ifdef __WXMSW__ - virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); -#endif // __WXMSW__ - -private: - DECLARE_DYNAMIC_CLASS_NO_COPY(wxGenericScrolledWindow) - DECLARE_EVENT_TABLE() -}; - #endif // _WX_GENERIC_SCROLLWIN_H_ diff --git a/include/wx/gtk/scrolwin.h b/include/wx/gtk/scrolwin.h index 960e8e87d2..92ecc160d7 100644 --- a/include/wx/gtk/scrolwin.h +++ b/include/wx/gtk/scrolwin.h @@ -2,7 +2,7 @@ // Name: wx/gtk/scrolwin.h // Purpose: wxScrolledWindow class // Author: Robert Roebling -// Modified by: +// Modified by: Vadim Zeitlin (2005-10-10): wxScrolledWindow is now common // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Robert Roebling @@ -12,182 +12,43 @@ #ifndef _WX_GTK_SCROLLWIN_H_ #define _WX_GTK_SCROLLWIN_H_ -// ---------------------------------------------------------------------------- -// headers and constants -// ---------------------------------------------------------------------------- - -#include "wx/window.h" -#include "wx/panel.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr; - -// default scrolled window style -#ifndef wxScrolledWindowStyle -#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) -#endif - // ---------------------------------------------------------------------------- // wxScrolledWindow // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxScrolledWindow : public wxPanel +class WXDLLEXPORT wxScrollHelperNative : public wxScrollHelper { public: - wxScrolledWindow() - { Init(); } - - wxScrolledWindow(wxWindow *parent, - wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr) - { Create(parent, id, pos, size, style, name); } - - void Init(); - - bool Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr); + // default ctor doesn't do anything + wxScrollHelperNative(wxWindow *win) : wxScrollHelper(win) { } - // Normally the wxScrolledWindow will scroll itself, but in - // some rare occasions you might want it to scroll another - // window (e.g. a child of it in order to scroll only a portion - // the area between the scrollbars (spreadsheet: only cell area - // will move). - virtual void SetTargetWindow( wxWindow *target, bool pushEventHandler = FALSE ); - virtual wxWindow *GetTargetWindow() const; - - // Set the scrolled area of the window. - virtual void DoSetVirtualSize( int x, int y ); - - // wxWindow's GetBestVirtualSize returns the actual window size, - // whereas we want to return the virtual size - virtual wxSize GetBestVirtualSize() const; - - // Return the size best suited for the current window - // (this isn't a virtual size, this is a sensible size for the window) - virtual wxSize DoGetBestSize() const; - - // Set the x, y scrolling increments. - void SetScrollRate( int xstep, int ystep ); - - // Number of pixels per user unit (0 or -1 for no scrollbar) - // Length of virtual canvas in user units - // Length of page in user units - // Default action is to set the virtual size and alter scrollbars - // accordingly. virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos = 0, int yPos = 0, - bool noRefresh = FALSE ); - - // Physically scroll the window - virtual void Scroll(int x_pos, int y_pos); - - int GetScrollPageSize(int orient) const; - void SetScrollPageSize(int orient, int pageSize); - - virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const; - - // Enable/disable Windows scrolling in either direction. - // If TRUE, wxWidgets scrolls the canvas and only a bit of - // the canvas is invalidated; no Clear() is necessary. - // If FALSE, the whole canvas is invalidated and a Clear() is - // necessary. Disable for when the scroll increment is used - // to actually scroll a non-constant distance - virtual void EnableScrolling(bool x_scrolling, bool y_scrolling); - - // Get the view start - virtual void GetViewStart(int *x, int *y) const; - - // translate between scrolled and unscrolled coordinates - void CalcScrolledPosition(int x, int y, int *xx, int *yy) const - { DoCalcScrolledPosition(x, y, xx, yy); } - wxPoint CalcScrolledPosition(const wxPoint& pt) const - { - wxPoint p2; - DoCalcScrolledPosition(pt.x, pt.y, &p2.x, &p2.y); - return p2; - } - - void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const - { DoCalcUnscrolledPosition(x, y, xx, yy); } - wxPoint CalcUnscrolledPosition(const wxPoint& pt) const - { - wxPoint p2; - DoCalcUnscrolledPosition(pt.x, pt.y, &p2.x, &p2.y); - return p2; - } - - virtual void DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const; - virtual void DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; - - // Override this function to draw the graphic (or just process EVT_PAINT) - virtual void OnDraw(wxDC& WXUNUSED(dc)) {} - - // Override this function if you don't want to have wxScrolledWindow - // automatically change the origin according to the scroll position. - void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } - - // lay out the window and its children - virtual bool Layout(); - - // Adjust the scrollbars + int noUnitsX, int noUnitsY, + int xPos = 0, int yPos = 0, + bool noRefresh = false); virtual void AdjustScrollbars(); - - // Set the scale factor, used in PrepareDC - void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; } - double GetScaleX() const { return m_scaleX; } - double GetScaleY() const { return m_scaleY; } - - // implementation from now on - void OnScroll(wxScrollWinEvent& event); - void OnSize(wxSizeEvent& event); - void OnPaint(wxPaintEvent& event); - void OnChar(wxKeyEvent& event); - - void GtkVScroll( float value, unsigned int scroll_type ); - void GtkHScroll( float value, unsigned int scroll_type ); - void GtkVConnectEvent(); - void GtkHConnectEvent(); - void GtkVDisconnectEvent(); - void GtkHDisconnectEvent(); - - // Calculate scroll increment - virtual int CalcScrollInc(wxScrollWinEvent& event); - - // Overridden from wxWidgets due callback being static - virtual void SetScrollPos( int orient, int pos, bool refresh = TRUE ); - - virtual void DoPrepareDC(wxDC& dc); + virtual void Scroll(int x, int y); protected: - wxWindow *m_targetWindow; - int m_xScrollPixelsPerLine; - int m_yScrollPixelsPerLine; - bool m_xScrollingEnabled; - bool m_yScrollingEnabled; - - // FIXME: these next four members are duplicated in the GtkAdjustment - // members of wxWindow. Can they be safely removed from here? - - int m_xScrollPosition; - int m_yScrollPosition; - int m_xScrollLinesPerPage; - int m_yScrollLinesPerPage; - - double m_scaleY,m_scaleX; + // this does (each) half of AdjustScrollbars() work + void DoAdjustScrollbar(GtkAdjustment *adj, + int pixelsPerLine, + int winSize, + int virtSize, + int *pos, + int *lines, + int *linesPerPage); + + // and this does the same for Scroll() + void DoScroll(int orient, + GtkAdjustment *adj, + int pos, + int pixelsPerLine, + int *posOld); private: - DECLARE_EVENT_TABLE() - DECLARE_DYNAMIC_CLASS(wxScrolledWindow) + DECLARE_NO_COPY_CLASS(wxScrollHelperNative) }; -#endif - // _WX_GTK_SCROLLWIN_H_ +#endif // _WX_GTK_SCROLLWIN_H_ -// vi:sts=4:sw=4:et diff --git a/include/wx/gtk1/scrolwin.h b/include/wx/gtk1/scrolwin.h index 960e8e87d2..92ecc160d7 100644 --- a/include/wx/gtk1/scrolwin.h +++ b/include/wx/gtk1/scrolwin.h @@ -2,7 +2,7 @@ // Name: wx/gtk/scrolwin.h // Purpose: wxScrolledWindow class // Author: Robert Roebling -// Modified by: +// Modified by: Vadim Zeitlin (2005-10-10): wxScrolledWindow is now common // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Robert Roebling @@ -12,182 +12,43 @@ #ifndef _WX_GTK_SCROLLWIN_H_ #define _WX_GTK_SCROLLWIN_H_ -// ---------------------------------------------------------------------------- -// headers and constants -// ---------------------------------------------------------------------------- - -#include "wx/window.h" -#include "wx/panel.h" - -WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr; - -// default scrolled window style -#ifndef wxScrolledWindowStyle -#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) -#endif - // ---------------------------------------------------------------------------- // wxScrolledWindow // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxScrolledWindow : public wxPanel +class WXDLLEXPORT wxScrollHelperNative : public wxScrollHelper { public: - wxScrolledWindow() - { Init(); } - - wxScrolledWindow(wxWindow *parent, - wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr) - { Create(parent, id, pos, size, style, name); } - - void Init(); - - bool Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr); + // default ctor doesn't do anything + wxScrollHelperNative(wxWindow *win) : wxScrollHelper(win) { } - // Normally the wxScrolledWindow will scroll itself, but in - // some rare occasions you might want it to scroll another - // window (e.g. a child of it in order to scroll only a portion - // the area between the scrollbars (spreadsheet: only cell area - // will move). - virtual void SetTargetWindow( wxWindow *target, bool pushEventHandler = FALSE ); - virtual wxWindow *GetTargetWindow() const; - - // Set the scrolled area of the window. - virtual void DoSetVirtualSize( int x, int y ); - - // wxWindow's GetBestVirtualSize returns the actual window size, - // whereas we want to return the virtual size - virtual wxSize GetBestVirtualSize() const; - - // Return the size best suited for the current window - // (this isn't a virtual size, this is a sensible size for the window) - virtual wxSize DoGetBestSize() const; - - // Set the x, y scrolling increments. - void SetScrollRate( int xstep, int ystep ); - - // Number of pixels per user unit (0 or -1 for no scrollbar) - // Length of virtual canvas in user units - // Length of page in user units - // Default action is to set the virtual size and alter scrollbars - // accordingly. virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos = 0, int yPos = 0, - bool noRefresh = FALSE ); - - // Physically scroll the window - virtual void Scroll(int x_pos, int y_pos); - - int GetScrollPageSize(int orient) const; - void SetScrollPageSize(int orient, int pageSize); - - virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const; - - // Enable/disable Windows scrolling in either direction. - // If TRUE, wxWidgets scrolls the canvas and only a bit of - // the canvas is invalidated; no Clear() is necessary. - // If FALSE, the whole canvas is invalidated and a Clear() is - // necessary. Disable for when the scroll increment is used - // to actually scroll a non-constant distance - virtual void EnableScrolling(bool x_scrolling, bool y_scrolling); - - // Get the view start - virtual void GetViewStart(int *x, int *y) const; - - // translate between scrolled and unscrolled coordinates - void CalcScrolledPosition(int x, int y, int *xx, int *yy) const - { DoCalcScrolledPosition(x, y, xx, yy); } - wxPoint CalcScrolledPosition(const wxPoint& pt) const - { - wxPoint p2; - DoCalcScrolledPosition(pt.x, pt.y, &p2.x, &p2.y); - return p2; - } - - void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const - { DoCalcUnscrolledPosition(x, y, xx, yy); } - wxPoint CalcUnscrolledPosition(const wxPoint& pt) const - { - wxPoint p2; - DoCalcUnscrolledPosition(pt.x, pt.y, &p2.x, &p2.y); - return p2; - } - - virtual void DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const; - virtual void DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; - - // Override this function to draw the graphic (or just process EVT_PAINT) - virtual void OnDraw(wxDC& WXUNUSED(dc)) {} - - // Override this function if you don't want to have wxScrolledWindow - // automatically change the origin according to the scroll position. - void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } - - // lay out the window and its children - virtual bool Layout(); - - // Adjust the scrollbars + int noUnitsX, int noUnitsY, + int xPos = 0, int yPos = 0, + bool noRefresh = false); virtual void AdjustScrollbars(); - - // Set the scale factor, used in PrepareDC - void SetScale(double xs, double ys) { m_scaleX = xs; m_scaleY = ys; } - double GetScaleX() const { return m_scaleX; } - double GetScaleY() const { return m_scaleY; } - - // implementation from now on - void OnScroll(wxScrollWinEvent& event); - void OnSize(wxSizeEvent& event); - void OnPaint(wxPaintEvent& event); - void OnChar(wxKeyEvent& event); - - void GtkVScroll( float value, unsigned int scroll_type ); - void GtkHScroll( float value, unsigned int scroll_type ); - void GtkVConnectEvent(); - void GtkHConnectEvent(); - void GtkVDisconnectEvent(); - void GtkHDisconnectEvent(); - - // Calculate scroll increment - virtual int CalcScrollInc(wxScrollWinEvent& event); - - // Overridden from wxWidgets due callback being static - virtual void SetScrollPos( int orient, int pos, bool refresh = TRUE ); - - virtual void DoPrepareDC(wxDC& dc); + virtual void Scroll(int x, int y); protected: - wxWindow *m_targetWindow; - int m_xScrollPixelsPerLine; - int m_yScrollPixelsPerLine; - bool m_xScrollingEnabled; - bool m_yScrollingEnabled; - - // FIXME: these next four members are duplicated in the GtkAdjustment - // members of wxWindow. Can they be safely removed from here? - - int m_xScrollPosition; - int m_yScrollPosition; - int m_xScrollLinesPerPage; - int m_yScrollLinesPerPage; - - double m_scaleY,m_scaleX; + // this does (each) half of AdjustScrollbars() work + void DoAdjustScrollbar(GtkAdjustment *adj, + int pixelsPerLine, + int winSize, + int virtSize, + int *pos, + int *lines, + int *linesPerPage); + + // and this does the same for Scroll() + void DoScroll(int orient, + GtkAdjustment *adj, + int pos, + int pixelsPerLine, + int *posOld); private: - DECLARE_EVENT_TABLE() - DECLARE_DYNAMIC_CLASS(wxScrolledWindow) + DECLARE_NO_COPY_CLASS(wxScrollHelperNative) }; -#endif - // _WX_GTK_SCROLLWIN_H_ +#endif // _WX_GTK_SCROLLWIN_H_ -// vi:sts=4:sw=4:et diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index f7614dbd1d..111136f453 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -17,19 +17,44 @@ class WXDLLEXPORT wxScrollHelperEvtHandler; class WXDLLEXPORT wxTimer; +WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr; + +// default scrolled window style: scroll in both directions +#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL) + // ---------------------------------------------------------------------------- -// wxScrollHelper: this class implements the scrolling logic which is used by -// wxScrolledWindow and wxScrolledControl. It is a mix-in: just derive from it -// to implement scrolling in your class. +// The hierarchy of scrolling classes is a bit complicated because we want to +// put as much functionality as possible in a mix-in class not deriving from +// wxWindow so that other classes could derive from the same base class on all +// platforms irrespectively of whether they are native controls (and hence +// don't use our scrolling) or not. +// +// So we have +// +// wxScrollHelper +// | +// | +// \|/ +// wxWindow wxScrollHelperNative +// | \ / / +// | \ / / +// | _| |_ / +// | wxScrolledWindow / +// | / +// \|/ / +// wxControl / +// \ / +// \ / +// _| |_ +// wxScrolledControl +// // ---------------------------------------------------------------------------- -#if !defined(__WXGTK__) || defined(__WXUNIVERSAL__) class WXDLLEXPORT wxScrollHelper { public: - // ctor and dtor - wxScrollHelper(wxWindow *winToScroll = (wxWindow *)NULL); - void SetWindow(wxWindow *winToScroll); + // ctor must be given the associated window + wxScrollHelper(wxWindow *winToScroll); virtual ~wxScrollHelper(); // configure the scrolling @@ -163,6 +188,13 @@ protected: *h = size.y; } + // implementations of various wxWindow virtual methods which should be + // forwarded to us (this can be done by WX_FORWARD_TO_SCROLL_HELPER()) + bool ScrollLayout(); + void ScrollDoSetVirtualSize(int x, int y); + wxSize ScrollGetBestVirtualSize() const; + wxSize ScrollGetWindowSizeForVirtualSize(const wxSize& size) const; + // change just the target window (unlike SetWindow which changes m_win as // well) void DoSetTargetWindow(wxWindow *target); @@ -170,6 +202,7 @@ protected: // delete the event handler we installed void DeleteEvtHandler(); + double m_scaleX; double m_scaleY; @@ -201,38 +234,71 @@ protected: DECLARE_NO_COPY_CLASS(wxScrollHelper) }; +// this macro can be used in a wxScrollHelper-derived class to forward wxWindow +// methods to corresponding wxScrollHelper methods +#define WX_FORWARD_TO_SCROLL_HELPER() \ + virtual void PrepareDC(wxDC& dc) { DoPrepareDC(dc); } \ + virtual bool Layout() { return ScrollLayout(); } \ + virtual void DoSetVirtualSize(int x, int y) \ + { ScrollDoSetVirtualSize(x, y); } \ + virtual wxSize GetBestVirtualSize() const \ + { return ScrollGetBestVirtualSize(); } \ + virtual wxSize GetWindowSizeForVirtualSize(const wxSize& size) const \ + { return ScrollGetWindowSizeForVirtualSize(size); } + +// include the declaration of wxScrollHelperNative if needed +#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) + #include "wx/gtk/scrolwin.h" +#else + typedef wxScrollHelper wxScrollHelperNative; #endif // ---------------------------------------------------------------------------- // wxScrolledWindow: a wxWindow which knows how to scroll // ---------------------------------------------------------------------------- -#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) - #include "wx/gtk/scrolwin.h" -#else // !wxGTK - #include "wx/generic/scrolwin.h" - - class WXDLLEXPORT wxScrolledWindow : public wxGenericScrolledWindow +class WXDLLEXPORT wxScrolledWindow : public wxPanel, + public wxScrollHelperNative +{ +public: + wxScrolledWindow() : wxScrollHelperNative(this) { } + wxScrolledWindow(wxWindow *parent, + wxWindowID winid = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxScrolledWindowStyle, + const wxString& name = wxPanelNameStr) + : wxScrollHelperNative(this) { - public: - wxScrolledWindow() { } - wxScrolledWindow(wxWindow *parent, - wxWindowID winid = wxID_ANY, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxScrolledWindowStyle, - const wxString& name = wxPanelNameStr) - : wxGenericScrolledWindow(parent, winid, pos, size, style, name) - { - } - - private: - DECLARE_DYNAMIC_CLASS_NO_COPY(wxScrolledWindow) - }; - - #define wxSCROLLED_WINDOW_IS_GENERIC 1 -#endif + Create(parent, winid, pos, size, style, name); + } -#endif - // _WX_SCROLWIN_H_BASE_ + virtual ~wxScrolledWindow(); + + bool Create(wxWindow *parent, + wxWindowID winid, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxScrolledWindowStyle, + const wxString& name = wxPanelNameStr); + + WX_FORWARD_TO_SCROLL_HELPER() + +protected: + // this is needed for wxEVT_PAINT processing hack described in + // wxScrollHelperEvtHandler::ProcessEvent() + void OnPaint(wxPaintEvent& event); + + // we need to return a special WM_GETDLGCODE value to process just the + // arrows but let the other navigation characters through +#ifdef __WXMSW__ + virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); +#endif // __WXMSW__ + +private: + DECLARE_DYNAMIC_CLASS_NO_COPY(wxScrolledWindow) + DECLARE_EVENT_TABLE() +}; + +#endif // _WX_SCROLWIN_H_BASE_ diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 37b281c062..be7802df03 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: generic/scrolwin.cpp -// Purpose: wxGenericScrolledWindow implementation +// Purpose: wxScrolledWindow implementation // Author: Julian Smart // Modified by: Vadim Zeitlin on 31.08.00: wxScrollHelper allows to implement. // Ron Lee on 10.4.02: virtual size / auto scrollbars et al. @@ -29,8 +29,6 @@ #pragma hdrstop #endif -#if !defined(__WXGTK__) || defined(__WXUNIVERSAL__) - #include "wx/utils.h" #include "wx/dcclient.h" @@ -59,8 +57,6 @@ #endif #endif -IMPLEMENT_CLASS(wxScrolledWindow, wxGenericScrolledWindow) - /* TODO PROPERTIES style wxHSCROLL | wxVSCROLL @@ -284,6 +280,8 @@ bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) wxScrollHelper::wxScrollHelper(wxWindow *win) { + wxASSERT_MSG( win, _T("associated window can't be NULL in wxScrollHelper") ); + m_xScrollPixelsPerLine = m_yScrollPixelsPerLine = m_xScrollPosition = @@ -309,8 +307,10 @@ wxScrollHelper::wxScrollHelper(wxWindow *win) m_handler = NULL; - if ( win ) - SetWindow(win); + m_win = win; + + // by default, the associated window is also the target window + DoSetTargetWindow(win); } wxScrollHelper::~wxScrollHelper() @@ -407,16 +407,6 @@ void wxScrollHelper::DeleteEvtHandler() } } -void wxScrollHelper::SetWindow(wxWindow *win) -{ - wxCHECK_RET( win, _T("wxScrollHelper needs a window to scroll") ); - - m_win = win; - - // by default, the associated window is also the target window - DoSetTargetWindow(win); -} - void wxScrollHelper::DoSetTargetWindow(wxWindow *target) { m_targetWindow = target; @@ -651,7 +641,7 @@ void wxScrollHelper::AdjustScrollbars() do { iterationCount ++; - + GetTargetSize(&w, 0); // scroll lines per page: if 0, no scrolling is needed @@ -956,6 +946,71 @@ void wxScrollHelper::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) co *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine; } +// ---------------------------------------------------------------------------- +// geometry +// ---------------------------------------------------------------------------- + +bool wxScrollHelper::ScrollLayout() +{ + if ( m_win->GetSizer() && m_targetWindow == m_win ) + { + // If we're the scroll target, take into account the + // virtual size and scrolled position of the window. + + int x, y, w, h; + CalcScrolledPosition(0,0, &x,&y); + m_win->GetVirtualSize(&w, &h); + m_win->GetSizer()->SetDimension(x, y, w, h); + return true; + } + + // fall back to default for LayoutConstraints + return m_win->wxWindow::Layout(); +} + +void wxScrollHelper::ScrollDoSetVirtualSize(int x, int y) +{ + m_win->wxWindow::DoSetVirtualSize( x, y ); + AdjustScrollbars(); + + if (m_win->GetAutoLayout()) + m_win->Layout(); +} + +// wxWindow's GetBestVirtualSize returns the actual window size, +// whereas we want to return the virtual size +wxSize wxScrollHelper::ScrollGetBestVirtualSize() const +{ + wxSize clientSize(m_win->GetClientSize()); + if ( m_win->GetSizer() ) + clientSize.IncTo(m_win->GetSizer()->CalcMin()); + + return clientSize; +} + +// return the window best size from the given best virtual size +wxSize +wxScrollHelper::ScrollGetWindowSizeForVirtualSize(const wxSize& size) const +{ + // Only use the content to set the window size in the direction + // where there's no scrolling; otherwise we're going to get a huge + // window in the direction in which scrolling is enabled + int ppuX, ppuY; + GetScrollPixelsPerUnit(&ppuX, &ppuY); + + wxSize minSize = m_win->GetMinSize(); + if ( !minSize.IsFullySpecified() ) + minSize = m_win->GetSize(); + + wxSize best(size); + if (ppuX > 0) + best.x = minSize.x; + if (ppuY > 0) + best.y = minSize.y; + + return best; +} + // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- @@ -966,7 +1021,7 @@ void wxScrollHelper::HandleOnSize(wxSizeEvent& WXUNUSED(event)) if ( m_targetWindow->GetAutoLayout() ) { wxSize size = m_targetWindow->GetBestVirtualSize(); - + // This will call ::Layout() and ::AdjustScrollbars() m_win->SetVirtualSize( size ); } @@ -1228,16 +1283,16 @@ void wxScrollHelper::HandleOnMouseWheel(wxMouseEvent& event) #endif // wxUSE_MOUSEWHEEL // ---------------------------------------------------------------------------- -// wxGenericScrolledWindow implementation +// wxScrolledWindow implementation // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxGenericScrolledWindow, wxPanel) +IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) -BEGIN_EVENT_TABLE(wxGenericScrolledWindow, wxPanel) - EVT_PAINT(wxGenericScrolledWindow::OnPaint) +BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel) + EVT_PAINT(wxScrolledWindow::OnPaint) END_EVENT_TABLE() -bool wxGenericScrolledWindow::Create(wxWindow *parent, +bool wxScrolledWindow::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -1254,92 +1309,11 @@ bool wxGenericScrolledWindow::Create(wxWindow *parent, return ok; } -wxGenericScrolledWindow::~wxGenericScrolledWindow() +wxScrolledWindow::~wxScrolledWindow() { } -bool wxGenericScrolledWindow::Layout() -{ - if (GetSizer() && m_targetWindow == this) - { - // If we're the scroll target, take into account the - // virtual size and scrolled position of the window. - - int x, y, w, h; - CalcScrolledPosition(0,0, &x,&y); - GetVirtualSize(&w, &h); - GetSizer()->SetDimension(x, y, w, h); - return true; - } - - // fall back to default for LayoutConstraints - return wxPanel::Layout(); -} - -void wxGenericScrolledWindow::DoSetVirtualSize(int x, int y) -{ - wxPanel::DoSetVirtualSize( x, y ); - AdjustScrollbars(); - - if (GetAutoLayout()) - Layout(); -} - -// wxWindow's GetBestVirtualSize returns the actual window size, -// whereas we want to return the virtual size -wxSize wxGenericScrolledWindow::GetBestVirtualSize() const -{ - wxSize clientSize( GetClientSize() ); - if (GetSizer()) - { - wxSize minSize( GetSizer()->CalcMin() ); - - return wxSize( wxMax( clientSize.x, minSize.x ), wxMax( clientSize.y, minSize.y ) ); - } - else - return clientSize; -} - -// return the size best suited for the current window -// (this isn't a virtual size, this is a sensible size for the window) -wxSize wxGenericScrolledWindow::DoGetBestSize() const -{ - wxSize best; - - if ( GetSizer() ) - { - wxSize b = GetSizer()->GetMinSize(); - - // Only use the content to set the window size in the direction - // where there's no scrolling; otherwise we're going to get a huge - // window in the direction in which scrolling is enabled - int ppuX, ppuY; - GetScrollPixelsPerUnit(& ppuX, & ppuY); - - wxSize minSize; - if ( GetMinSize().IsFullySpecified() ) - minSize = GetMinSize(); - else - minSize = GetSize(); - - if (ppuX > 0) - b.x = minSize.x; - if (ppuY > 0) - b.y = minSize.y; - best = b; - } - else - return wxWindow::DoGetBestSize(); - - // Add any difference between size and client size - wxSize diff = GetSize() - GetClientSize(); - best.x += wxMax(0, diff.x); - best.y += wxMax(0, diff.y); - - return best; -} - -void wxGenericScrolledWindow::OnPaint(wxPaintEvent& event) +void wxScrolledWindow::OnPaint(wxPaintEvent& event) { // the user code didn't really draw the window if we got here, so set this // flag to try to call OnDraw() later @@ -1349,8 +1323,7 @@ void wxGenericScrolledWindow::OnPaint(wxPaintEvent& event) } #ifdef __WXMSW__ -WXLRESULT -wxGenericScrolledWindow::MSWWindowProc(WXUINT nMsg, +WXLRESULT wxScrolledWindow::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { @@ -1369,6 +1342,3 @@ wxGenericScrolledWindow::MSWWindowProc(WXUINT nMsg, #endif // __WXMSW__ -#endif // !wxGTK - -// vi:sts=4:sw=4:et diff --git a/src/gtk/scrolwin.cpp b/src/gtk/scrolwin.cpp index 80ba00f515..70a9298be2 100644 --- a/src/gtk/scrolwin.cpp +++ b/src/gtk/scrolwin.cpp @@ -3,6 +3,7 @@ // Purpose: wxScrolledWindow implementation // Author: Robert Roebling // Modified by: Ron Lee +// Vadim Zeitlin: removed 90% of duplicated common code // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Robert Roebling @@ -25,379 +26,23 @@ #endif #include "wx/scrolwin.h" -#include "wx/utils.h" -#include "wx/dcclient.h" -#include "wx/panel.h" -#include "wx/sizer.h" -#include "wx/math.h" - #include "wx/gtk/private.h" -#include "wx/gtk/win_gtk.h" - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- - -BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel) - EVT_SCROLLWIN(wxScrolledWindow::OnScroll) - EVT_SIZE(wxScrolledWindow::OnSize) - EVT_PAINT(wxScrolledWindow::OnPaint) - EVT_CHAR(wxScrolledWindow::OnChar) -END_EVENT_TABLE() - -IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) // ============================================================================ // implementation // ============================================================================ -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- - -extern bool g_blockEventsOnDrag; -extern bool g_blockEventsOnScroll; - -//----------------------------------------------------------------------------- -// idle system -//----------------------------------------------------------------------------- - -extern void wxapp_install_idle_handler(); -extern bool g_isIdle; - -//----------------------------------------------------------------------------- -// "value_changed" from m_vAdjust -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, - SCROLLBAR_CBACK_ARG - wxScrolledWindow *win ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - if (g_blockEventsOnDrag) return; - - if (!win->m_hasVMT) return; - - win->GtkVScroll( adjust->value, - GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->vscrollbar) ); -} -} - -//----------------------------------------------------------------------------- -// "value_changed" from m_hAdjust -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, - SCROLLBAR_CBACK_ARG - wxScrolledWindow *win ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - if (g_blockEventsOnDrag) return; - if (!win->m_hasVMT) return; - - win->GtkHScroll( adjust->value, - GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->hscrollbar) ); -} -} - -//----------------------------------------------------------------------------- -// "button_press_event" from scrollbar -//----------------------------------------------------------------------------- - -extern "C" { -static gint gtk_scrollbar_button_press_callback( GtkRange *widget, - GdkEventButton *gdk_event, - wxWindowGTK *win) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - g_blockEventsOnScroll = TRUE; - - // FIXME: there is no slider field any more, what was meant here? -#ifndef __WXGTK20__ - win->m_isScrolling = (gdk_event->window == widget->slider); -#endif - - return FALSE; -} -} - -//----------------------------------------------------------------------------- -// "button_release_event" from scrollbar -//----------------------------------------------------------------------------- - -extern "C" { -static gint gtk_scrollbar_button_release_callback( GtkRange *widget, - GdkEventButton *WXUNUSED(gdk_event), - wxWindowGTK *win) -{ -// don't test here as we can release the mouse while being over -// a different window than the slider -// -// if (gdk_event->window != widget->slider) return FALSE; - - g_blockEventsOnScroll = FALSE; - - if (win->m_isScrolling) - { - wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE; - int value = -1; - int dir = -1; - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); - if (widget == GTK_RANGE(scrolledWindow->hscrollbar)) - { - value = (int)(win->m_hAdjust->value+0.5); - dir = wxHORIZONTAL; - } - if (widget == GTK_RANGE(scrolledWindow->vscrollbar)) - { - value = (int)(win->m_vAdjust->value+0.5); - dir = wxVERTICAL; - } - - wxScrollWinEvent event( command, value, dir ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); - } - - win->m_isScrolling = FALSE; - - return FALSE; -} -} - -//----------------------------------------------------------------------------- -// InsertChild for wxScrolledWindow -//----------------------------------------------------------------------------- - -static void wxInsertChildInScrolledWindow( wxWindow* parent, wxWindow* child ) -{ - // The window might have been scrolled already, do we - // have to adapt the position. - GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow); - child->m_x += pizza->xoffset; - child->m_y += pizza->yoffset; - - gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow), - GTK_WIDGET(child->m_widget), - child->m_x, - child->m_y, - child->m_width, - child->m_height ); -} - -// ---------------------------------------------------------------------------- -// wxScrolledWindow creation -// ---------------------------------------------------------------------------- - -void wxScrolledWindow::Init() -{ - m_xScrollPixelsPerLine = 0; - m_yScrollPixelsPerLine = 0; - m_xScrollingEnabled = TRUE; - m_yScrollingEnabled = TRUE; - m_xScrollPosition = 0; - m_yScrollPosition = 0; - m_xScrollLinesPerPage = 0; - m_yScrollLinesPerPage = 0; - m_targetWindow = (wxWindow*) NULL; - m_scaleX = 1.0; - m_scaleY = 1.0; - m_hasScrolling = TRUE; -} - -bool wxScrolledWindow::Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) -{ - Init(); - - if (!PreCreation( parent, pos, size ) || - !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) - { - wxFAIL_MSG( wxT("wxWindow creation failed") ); - return FALSE; - } - - m_insertCallback = wxInsertChildInScrolledWindow; - - m_targetWindow = this; - - m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); - GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - - GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) ); - scroll_class->scrollbar_spacing = 0; - - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - - m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) ); - m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) ); - - m_wxwindow = gtk_pizza_new(); - - gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); - - GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - - if (HasFlag(wxRAISED_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT ); - } - else if (HasFlag(wxSUNKEN_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN ); - } - else if (HasFlag(wxSIMPLE_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN ); - } - else - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE ); - } - - GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); - m_acceptsFocus = TRUE; - - // I _really_ don't want scrollbars in the beginning - m_vAdjust->lower = 0.0; - m_vAdjust->upper = 1.0; - m_vAdjust->value = 0.0; - m_vAdjust->step_increment = 1.0; - m_vAdjust->page_increment = 2.0; - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); - m_hAdjust->lower = 0.0; - m_hAdjust->upper = 1.0; - m_hAdjust->value = 0.0; - m_hAdjust->step_increment = 1.0; - m_hAdjust->page_increment = 2.0; - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); - - // Handlers for new scrollbar values - GtkVConnectEvent(); - GtkHConnectEvent(); - - // these handlers block mouse events to any window during scrolling such as - // motion events and prevent GTK and wxWidgets from fighting over where the - // slider should be - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", - (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event", - (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event", - (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event", - (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); - - gtk_widget_show( m_wxwindow ); - - if (m_parent) - m_parent->DoAddChild( this ); - - m_focusWidget = m_wxwindow; - - PostCreation(); - - Show( TRUE ); - - return TRUE; -} - // ---------------------------------------------------------------------------- -// setting scrolling parameters +// wxScrollHelper implementation // ---------------------------------------------------------------------------- -void wxScrolledWindow::DoSetVirtualSize( int x, int y ) -{ - wxPanel::DoSetVirtualSize( x, y ); - AdjustScrollbars(); - - if (GetAutoLayout()) - Layout(); -} - -// wxWindow's GetBestVirtualSize returns the actual window size, -// whereas we want to return the virtual size -wxSize wxScrolledWindow::GetBestVirtualSize() const -{ - wxSize clientSize( GetClientSize() ); - if (GetSizer()) - { - wxSize minSize( GetSizer()->CalcMin() ); - - return wxSize( wxMax( clientSize.x, minSize.x ), wxMax( clientSize.y, minSize.y ) ); - } - else - return clientSize; -} - -// return the size best suited for the current window -// (this isn't a virtual size, this is a sensible size for the window) -wxSize wxScrolledWindow::DoGetBestSize() const -{ - wxSize best; - - if ( GetSizer() ) - { - wxSize b = GetSizer()->GetMinSize(); - - // Only use the content to set the window size in the direction - // where there's no scrolling; otherwise we're going to get a huge - // window in the direction in which scrolling is enabled - int ppuX, ppuY; - GetScrollPixelsPerUnit(& ppuX, & ppuY); - - wxSize minSize; - if ( GetMinSize().IsFullySpecified() ) - minSize = GetMinSize(); - else - minSize = GetSize(); - - if (ppuX > 0) - b.x = minSize.x; - if (ppuY > 0) - b.y = minSize.y; - best = b; - } - else - return wxWindow::DoGetBestSize(); - - // Add any difference between size and client size - wxSize diff = GetSize() - GetClientSize(); - best.x += wxMax(0, diff.x); - best.y += wxMax(0, diff.y); - - return best; -} - -/* - * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) - * noUnitsX/noUnitsY: : no. units per scrollbar - */ -void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos, int yPos, bool noRefresh ) +void wxScrollHelperNative::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, + int noUnitsX, int noUnitsY, + int xPos, int yPos, + bool noRefresh) { int xs, ys; - GetViewStart (& xs, & ys); + GetViewStart(& xs, & ys); int old_x = m_xScrollPixelsPerLine * xs; int old_y = m_yScrollPixelsPerLine * ys; @@ -405,8 +50,8 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, m_xScrollPixelsPerLine = pixelsPerUnitX; m_yScrollPixelsPerLine = pixelsPerUnitY; - m_hAdjust->value = m_xScrollPosition = xPos; - m_vAdjust->value = m_yScrollPosition = yPos; + m_win->m_hAdjust->value = m_xScrollPosition = xPos; + m_win->m_vAdjust->value = m_yScrollPosition = yPos; // Setting hints here should arguably be deprecated, but without it // a sizer might override this manual scrollbar setting in old code. @@ -424,621 +69,113 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y ); } + + m_targetWindow->m_hasScrolling = pixelsPerUnitX || pixelsPerUnitY; } -void wxScrolledWindow::AdjustScrollbars() +void wxScrollHelperNative::DoAdjustScrollbar(GtkAdjustment *adj, + int pixelsPerLine, + int winSize, + int virtSize, + int *pos, + int *lines, + int *linesPerPage) { - int w, h; - int vw, vh; - - m_targetWindow->GetClientSize( &w, &h ); - m_targetWindow->GetVirtualSize( &vw, &vh ); - - if (m_xScrollPixelsPerLine == 0) + if ( pixelsPerLine == 0 ) { - m_hAdjust->upper = 1.0; - m_hAdjust->page_increment = 1.0; - m_hAdjust->page_size = 1.0; + adj->upper = 1.0; + adj->page_increment = 1.0; + adj->page_size = 1.0; } - else + else // we do have scrollbar { - m_hAdjust->upper = (vw+m_xScrollPixelsPerLine-1) / m_xScrollPixelsPerLine; - m_hAdjust->page_size = w / m_xScrollPixelsPerLine; - m_hAdjust->page_increment = w / m_xScrollPixelsPerLine; + adj->upper = (virtSize + pixelsPerLine - 1) / pixelsPerLine; + adj->page_size = winSize / pixelsPerLine; + adj->page_increment = winSize / pixelsPerLine; // Special case. When client and virtual size are very close but // the client is big enough, kill scrollbar. - if ((m_hAdjust->page_size < m_hAdjust->upper) && (w >= vw)) - m_hAdjust->page_size += 1.0; + if ((adj->page_size < adj->upper) && (winSize >= virtSize)) + adj->page_size += 1.0; // If the scrollbar hits the right side, move the window // right to keep it from over extending. - if ( !wxIsNullDouble(m_hAdjust->value) && - (m_hAdjust->value + m_hAdjust->page_size > m_hAdjust->upper) ) + if ( !wxIsNullDouble(adj->value) && + (adj->value + adj->page_size > adj->upper) ) { - m_hAdjust->value = m_hAdjust->upper - m_hAdjust->page_size; - if (m_hAdjust->value < 0.0) - m_hAdjust->value = 0.0; - - if (GetChildren().GetCount() == 0) - m_xScrollPosition = (int)m_hAdjust->value; // This is enough without child windows + adj->value = adj->upper - adj->page_size; + if (adj->value < 0.0) + adj->value = 0.0; + + if ( m_win->GetChildren().empty() ) + { + // This is enough without child windows + *pos = (int)adj->value; + } else - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); // Actually scroll window + { + // We need to actually scroll window + gtk_signal_emit_by_name( GTK_OBJECT(adj), "value_changed" ); + } } } - if (m_yScrollPixelsPerLine == 0) - { - m_vAdjust->upper = 1.0; - m_vAdjust->page_increment = 1.0; - m_vAdjust->page_size = 1.0; - } - else - { - m_vAdjust->upper = (vh+m_yScrollPixelsPerLine-1) / m_yScrollPixelsPerLine; - m_vAdjust->page_size = h / m_yScrollPixelsPerLine; - m_vAdjust->page_increment = h / m_yScrollPixelsPerLine; - - if ((m_vAdjust->page_size < m_vAdjust->upper) && (h >= vh)) - m_vAdjust->page_size += 1.0; - - if ( !wxIsNullDouble(m_vAdjust->value) && - (m_vAdjust->value + m_vAdjust->page_size > m_vAdjust->upper) ) - { - m_vAdjust->value = m_vAdjust->upper - m_vAdjust->page_size; - if (m_vAdjust->value < 0.0) - m_vAdjust->value = 0.0; - - if (GetChildren().GetCount() == 0) - m_yScrollPosition = (int)m_vAdjust->value; - else - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - } - } - - m_xScrollLinesPerPage = (int)(m_hAdjust->page_increment + 0.5); - m_yScrollLinesPerPage = (int)(m_vAdjust->page_increment + 0.5); - - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); -} - - -// ---------------------------------------------------------------------------- -// target window handling -// ---------------------------------------------------------------------------- - -void wxScrolledWindow::SetTargetWindow( wxWindow *target, bool WXUNUSED(pushEventHandler) ) -{ - wxASSERT_MSG( target, wxT("target window must not be NULL") ); - m_targetWindow = target; -} - -wxWindow *wxScrolledWindow::GetTargetWindow() const -{ - return m_targetWindow; -} - -// Override this function if you don't want to have wxScrolledWindow -// automatically change the origin according to the scroll position. -void wxScrolledWindow::DoPrepareDC(wxDC& dc) -{ - dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, - -m_yScrollPosition * m_yScrollPixelsPerLine ); + *lines = (int)(adj->upper + 0.5); + *linesPerPage = (int)(adj->page_increment + 0.5); + gtk_signal_emit_by_name( GTK_OBJECT(adj), "changed" ); } -void wxScrolledWindow::SetScrollRate( int xstep, int ystep ) +void wxScrollHelperNative::AdjustScrollbars() { - int old_x = m_xScrollPixelsPerLine * m_xScrollPosition; - int old_y = m_yScrollPixelsPerLine * m_yScrollPosition; - - m_xScrollPixelsPerLine = xstep; - m_yScrollPixelsPerLine = ystep; - - int new_x = m_xScrollPixelsPerLine * m_xScrollPosition; - int new_y = m_yScrollPixelsPerLine * m_yScrollPosition; - - m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y ); - - AdjustScrollbars(); -} - -void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const -{ - if ( x_unit ) - *x_unit = m_xScrollPixelsPerLine; - if ( y_unit ) - *y_unit = m_yScrollPixelsPerLine; -} - -int wxScrolledWindow::GetScrollPageSize(int orient) const -{ - if ( orient == wxHORIZONTAL ) - return m_xScrollLinesPerPage; - else - return m_yScrollLinesPerPage; -} - -void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize) -{ - if ( orient == wxHORIZONTAL ) - m_xScrollLinesPerPage = pageSize; - else - m_yScrollLinesPerPage = pageSize; -} - -void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) -{ - int orient = event.GetOrientation(); - - int nScrollInc = CalcScrollInc(event); - if (nScrollInc == 0) return; - - if (orient == wxHORIZONTAL) - { - int newPos = m_xScrollPosition + nScrollInc; - SetScrollPos(wxHORIZONTAL, newPos, TRUE ); - } - else - { - int newPos = m_yScrollPosition + nScrollInc; - SetScrollPos(wxVERTICAL, newPos, TRUE ); - } - - if (orient == wxHORIZONTAL) - { - m_xScrollPosition += nScrollInc; - } - else - { - m_yScrollPosition += nScrollInc; - } - - if (orient == wxHORIZONTAL) - { - if (m_xScrollingEnabled) - m_targetWindow->ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, (const wxRect *) NULL); - else - m_targetWindow->Refresh(); - } - else - { - if (m_yScrollingEnabled) - m_targetWindow->ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, (const wxRect *) NULL); - else - m_targetWindow->Refresh(); - } -} - -void wxScrolledWindow::Scroll( int x_pos, int y_pos ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (((x_pos == -1) || (x_pos == m_xScrollPosition)) && - ((y_pos == -1) || (y_pos == m_yScrollPosition))) return; - - if ((x_pos != -1) && (m_xScrollPixelsPerLine)) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - if (x_pos > max) x_pos = max; - if (x_pos < 0) x_pos = 0; - - int old_x = m_xScrollPosition; - m_xScrollPosition = x_pos; - m_hAdjust->value = x_pos; - - m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); - - // Just update the scrollbar, don't send any wxWidgets event - GtkHDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); - GtkHConnectEvent(); - } - - if ((y_pos != -1) && (m_yScrollPixelsPerLine)) - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - if (y_pos > max) y_pos = max; - if (y_pos < 0) y_pos = 0; - - int old_y = m_yScrollPosition; - m_yScrollPosition = y_pos; - m_vAdjust->value = y_pos; - - m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); - - // Just update the scrollbar, don't send any wxWidgets event - GtkVDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - GtkVConnectEvent(); - } -} - -// TODO: [VH]Scroll functions should be combined - -void wxScrolledWindow::GtkVScroll( float value, unsigned int scroll_type ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (m_yScrollPixelsPerLine == 0) - return; - - int y_pos = (int)(value+0.5); - - if (y_pos == m_yScrollPosition) - return; - - wxEventType command = GtkScrollWinTypeToWx(scroll_type); - - wxScrollWinEvent event( command, y_pos, wxVERTICAL ); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent( event ); -} - -void wxScrolledWindow::GtkHScroll( float value, unsigned int scroll_type ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (m_xScrollPixelsPerLine == 0) - return; - - int x_pos = (int)(value+0.5); - - if (x_pos == m_xScrollPosition) - return; - - wxEventType command = GtkScrollWinTypeToWx(scroll_type); - - wxScrollWinEvent event( command, x_pos, wxHORIZONTAL ); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent( event ); -} - -void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) -{ - m_xScrollingEnabled = x_scroll; - m_yScrollingEnabled = y_scroll; -} - -// Where the current view starts from -void wxScrolledWindow::GetViewStart (int *x, int *y) const -{ - if ( x ) - *x = m_xScrollPosition; - if ( y ) - *y = m_yScrollPosition; -} - -void wxScrolledWindow::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const -{ - int xs, ys; - GetViewStart (& xs, & ys); - - if ( xx ) - *xx = x - xs * m_xScrollPixelsPerLine; - if ( yy ) - *yy = y - ys * m_yScrollPixelsPerLine; -} - -void wxScrolledWindow::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const -{ - int xs, ys; - GetViewStart (& xs, & ys); - - if ( xx ) - *xx = x + xs * m_xScrollPixelsPerLine; - if ( yy ) - *yy = y + ys * m_yScrollPixelsPerLine; -} - -int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) -{ - int pos = event.GetPosition(); - int orient = event.GetOrientation(); - - int nScrollInc = 0; - if (event.GetEventType() == wxEVT_SCROLLWIN_TOP) - { - if (orient == wxHORIZONTAL) - nScrollInc = - m_xScrollPosition; - else - nScrollInc = - m_yScrollPosition; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM) - { - if (orient == wxHORIZONTAL) - nScrollInc = GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine - m_xScrollPosition; - else - nScrollInc = GetVirtualSize().GetHeight() / m_yScrollPixelsPerLine - m_yScrollPosition; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) - { - nScrollInc = -1; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) - { - nScrollInc = 1; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP) - { - if (orient == wxHORIZONTAL) - nScrollInc = -GetScrollPageSize(wxHORIZONTAL); - else - nScrollInc = -GetScrollPageSize(wxVERTICAL); - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN) - { - if (orient == wxHORIZONTAL) - nScrollInc = GetScrollPageSize(wxHORIZONTAL); - else - nScrollInc = GetScrollPageSize(wxVERTICAL); - } else - if ((event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) || - (event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE)) - { - if (orient == wxHORIZONTAL) - nScrollInc = pos - m_xScrollPosition; - else - nScrollInc = pos - m_yScrollPosition; - } - - if (orient == wxHORIZONTAL) - { - if (m_xScrollPixelsPerLine > 0) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if ( (m_xScrollPosition + nScrollInc) < 0 ) - nScrollInc = -m_xScrollPosition; // As -ve as we can go - else if ( (m_xScrollPosition + nScrollInc) > max ) - nScrollInc = max - m_xScrollPosition; // As +ve as we can go - } - else - m_targetWindow->Refresh(); - } - else - { - if (m_yScrollPixelsPerLine > 0) - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if ( (m_yScrollPosition + nScrollInc) < 0 ) - nScrollInc = -m_yScrollPosition; // As -ve as we can go - else if ( (m_yScrollPosition + nScrollInc) > max ) - nScrollInc = max - m_yScrollPosition; // As +ve as we can go - } - else - m_targetWindow->Refresh(); - } - - return nScrollInc; -} - -void wxScrolledWindow::SetScrollPos( int orient, int pos, bool refresh ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); - - if (orient == wxHORIZONTAL) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if (pos > max) pos = 0; - if (pos < 0) pos = 0; - - if (pos == (int)(m_hAdjust->value+0.5)) return; - m_hAdjust->value = pos; - } - else - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if (pos > max) pos = 0; - if (pos < 0) pos = 0; - - if (pos == (int)(m_vAdjust->value+0.5)) return; - m_vAdjust->value = pos; - } - - if (m_wxwindow->window) - { - if (orient == wxHORIZONTAL) - { - // Just update the scrollbar, don't send any wxWidgets event - GtkHDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); - GtkHConnectEvent(); - } - else - { - // Just update the scrollbar, don't send any wxWidgets event - GtkVDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - GtkVConnectEvent(); - } - } -} - -void wxScrolledWindow::GtkVConnectEvent() -{ - gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed", - (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this ); -} - -void wxScrolledWindow::GtkHConnectEvent() -{ - gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed", - (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this ); -} + int w, h; + int vw, vh; -void wxScrolledWindow::GtkHDisconnectEvent() -{ - gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust), - (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this ); -} + m_targetWindow->GetClientSize( &w, &h ); + m_targetWindow->GetVirtualSize( &vw, &vh ); -void wxScrolledWindow::GtkVDisconnectEvent() -{ - gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust), - (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this ); + DoAdjustScrollbar(m_win->m_hAdjust, m_xScrollPixelsPerLine, w, vw, + &m_xScrollPosition, &m_xScrollLines, &m_xScrollLinesPerPage); + DoAdjustScrollbar(m_win->m_vAdjust, m_yScrollPixelsPerLine, h, vh, + &m_yScrollPosition, &m_yScrollLines, &m_yScrollLinesPerPage); } -bool wxScrolledWindow::Layout() +void wxScrollHelperNative::DoScroll(int orient, + GtkAdjustment *adj, + int pos, + int pixelsPerLine, + int *posOld) { - if (GetSizer() && m_targetWindow == this) + if ( pos != -1 && pos != *posOld && pixelsPerLine ) { - // If we're the scroll target, take into account the - // virtual size and scrolled position of the window. + int max = (int)(adj->upper - adj->page_size + 0.5); + if (max < 0) + max = 0; + if (pos > max) + pos = max; + if (pos < 0) + pos = 0; - int x, y, w, h; - CalcScrolledPosition(0,0, &x,&y); - GetVirtualSize(&w, &h); - GetSizer()->SetDimension(x, y, w, h); - return TRUE; - } - else - return wxPanel::Layout(); // fall back to default for LayoutConstraints -} + adj->value = pos; -// ---------------------------------------------------------------------------- -// event handlers -// ---------------------------------------------------------------------------- + int diff = (*posOld - pos)*pixelsPerLine; + m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0, + orient == wxHORIZONTAL ? 0 : diff); -// Default OnSize resets scrollbars, if any -void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - if ( m_targetWindow->GetAutoLayout() ) - { - wxSize size = m_targetWindow->GetBestVirtualSize(); + *posOld = pos; - // This will call ::Layout() and ::AdjustScrollbars() - SetVirtualSize( size ); - } - else - { - AdjustScrollbars(); + m_win->GtkUpdateScrollbar(orient); } } -// This calls OnDraw, having adjusted the origin according to the current -// scroll position -void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) +void wxScrollHelperNative::Scroll( int x_pos, int y_pos ) { - wxPaintDC dc(this); - PrepareDC(dc); - - OnDraw(dc); -} - -// kbd handling: notice that we use OnChar() and not OnKeyDown() for -// compatibility here - if we used OnKeyDown(), the programs which process -// arrows themselves in their OnChar() would never get the message and like -// this they always have the priority -void wxScrolledWindow::OnChar(wxKeyEvent& event) -{ - int stx, sty, // view origin - szx, szy, // view size (total) - clix, cliy; // view size (on screen) - - GetViewStart(&stx, &sty); - GetClientSize(&clix, &cliy); - GetVirtualSize(&szx, &szy); - - if( m_xScrollPixelsPerLine ) - { - clix /= m_xScrollPixelsPerLine; - szx /= m_xScrollPixelsPerLine; - } - else - { - clix = 0; - szx = -1; - } - if( m_yScrollPixelsPerLine ) - { - cliy /= m_yScrollPixelsPerLine; - szy /= m_yScrollPixelsPerLine; - } - else - { - cliy = 0; - szy = -1; - } - - int xScrollOld = GetScrollPos(wxHORIZONTAL), - yScrollOld = GetScrollPos(wxVERTICAL); - - int dsty; - switch ( event.GetKeyCode() ) - { - case WXK_PAGEUP: - case WXK_PRIOR: - dsty = sty - (5 * cliy / 6); - Scroll(-1, (dsty == -1) ? 0 : dsty); - break; - - case WXK_PAGEDOWN: - case WXK_NEXT: - Scroll(-1, sty + (5 * cliy / 6)); - break; - - case WXK_HOME: - Scroll(0, event.ControlDown() ? 0 : -1); - break; - - case WXK_END: - Scroll(szx - clix, event.ControlDown() ? szy - cliy : -1); - break; - - case WXK_UP: - Scroll(-1, sty - 1); - break; - - case WXK_DOWN: - Scroll(-1, sty + 1); - break; + wxCHECK_RET( m_targetWindow != 0, _T("No target window") ); - case WXK_LEFT: - Scroll(stx - 1, -1); - break; - - case WXK_RIGHT: - Scroll(stx + 1, -1); - break; - - default: - // not for us - event.Skip(); - return; - } - - int xScroll = GetScrollPos(wxHORIZONTAL); - if ( xScroll != xScrollOld ) - { - wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, xScroll, - wxHORIZONTAL); - eventS.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventS); - } - - int yScroll = GetScrollPos(wxVERTICAL); - if ( yScroll != yScrollOld ) - { - wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, yScroll, - wxVERTICAL); - eventS.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventS); - } + DoScroll(wxHORIZONTAL, m_win->m_hAdjust, x_pos, m_xScrollPixelsPerLine, + &m_xScrollPosition); + DoScroll(wxVERTICAL, m_win->m_vAdjust, y_pos, m_yScrollPixelsPerLine, + &m_yScrollPosition); } - -// vi:sts=4:sw=4:et diff --git a/src/gtk1/scrolwin.cpp b/src/gtk1/scrolwin.cpp index 80ba00f515..70a9298be2 100644 --- a/src/gtk1/scrolwin.cpp +++ b/src/gtk1/scrolwin.cpp @@ -3,6 +3,7 @@ // Purpose: wxScrolledWindow implementation // Author: Robert Roebling // Modified by: Ron Lee +// Vadim Zeitlin: removed 90% of duplicated common code // Created: 01/02/97 // RCS-ID: $Id$ // Copyright: (c) Robert Roebling @@ -25,379 +26,23 @@ #endif #include "wx/scrolwin.h" -#include "wx/utils.h" -#include "wx/dcclient.h" -#include "wx/panel.h" -#include "wx/sizer.h" -#include "wx/math.h" - #include "wx/gtk/private.h" -#include "wx/gtk/win_gtk.h" - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- - -BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel) - EVT_SCROLLWIN(wxScrolledWindow::OnScroll) - EVT_SIZE(wxScrolledWindow::OnSize) - EVT_PAINT(wxScrolledWindow::OnPaint) - EVT_CHAR(wxScrolledWindow::OnChar) -END_EVENT_TABLE() - -IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxPanel) // ============================================================================ // implementation // ============================================================================ -//----------------------------------------------------------------------------- -// data -//----------------------------------------------------------------------------- - -extern bool g_blockEventsOnDrag; -extern bool g_blockEventsOnScroll; - -//----------------------------------------------------------------------------- -// idle system -//----------------------------------------------------------------------------- - -extern void wxapp_install_idle_handler(); -extern bool g_isIdle; - -//----------------------------------------------------------------------------- -// "value_changed" from m_vAdjust -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, - SCROLLBAR_CBACK_ARG - wxScrolledWindow *win ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - if (g_blockEventsOnDrag) return; - - if (!win->m_hasVMT) return; - - win->GtkVScroll( adjust->value, - GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->vscrollbar) ); -} -} - -//----------------------------------------------------------------------------- -// "value_changed" from m_hAdjust -//----------------------------------------------------------------------------- - -extern "C" { -static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, - SCROLLBAR_CBACK_ARG - wxScrolledWindow *win ) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - if (g_blockEventsOnDrag) return; - if (!win->m_hasVMT) return; - - win->GtkHScroll( adjust->value, - GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win->m_widget)->hscrollbar) ); -} -} - -//----------------------------------------------------------------------------- -// "button_press_event" from scrollbar -//----------------------------------------------------------------------------- - -extern "C" { -static gint gtk_scrollbar_button_press_callback( GtkRange *widget, - GdkEventButton *gdk_event, - wxWindowGTK *win) -{ - if (g_isIdle) - wxapp_install_idle_handler(); - - g_blockEventsOnScroll = TRUE; - - // FIXME: there is no slider field any more, what was meant here? -#ifndef __WXGTK20__ - win->m_isScrolling = (gdk_event->window == widget->slider); -#endif - - return FALSE; -} -} - -//----------------------------------------------------------------------------- -// "button_release_event" from scrollbar -//----------------------------------------------------------------------------- - -extern "C" { -static gint gtk_scrollbar_button_release_callback( GtkRange *widget, - GdkEventButton *WXUNUSED(gdk_event), - wxWindowGTK *win) -{ -// don't test here as we can release the mouse while being over -// a different window than the slider -// -// if (gdk_event->window != widget->slider) return FALSE; - - g_blockEventsOnScroll = FALSE; - - if (win->m_isScrolling) - { - wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE; - int value = -1; - int dir = -1; - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget); - if (widget == GTK_RANGE(scrolledWindow->hscrollbar)) - { - value = (int)(win->m_hAdjust->value+0.5); - dir = wxHORIZONTAL; - } - if (widget == GTK_RANGE(scrolledWindow->vscrollbar)) - { - value = (int)(win->m_vAdjust->value+0.5); - dir = wxVERTICAL; - } - - wxScrollWinEvent event( command, value, dir ); - event.SetEventObject( win ); - win->GetEventHandler()->ProcessEvent( event ); - } - - win->m_isScrolling = FALSE; - - return FALSE; -} -} - -//----------------------------------------------------------------------------- -// InsertChild for wxScrolledWindow -//----------------------------------------------------------------------------- - -static void wxInsertChildInScrolledWindow( wxWindow* parent, wxWindow* child ) -{ - // The window might have been scrolled already, do we - // have to adapt the position. - GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow); - child->m_x += pizza->xoffset; - child->m_y += pizza->yoffset; - - gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow), - GTK_WIDGET(child->m_widget), - child->m_x, - child->m_y, - child->m_width, - child->m_height ); -} - -// ---------------------------------------------------------------------------- -// wxScrolledWindow creation -// ---------------------------------------------------------------------------- - -void wxScrolledWindow::Init() -{ - m_xScrollPixelsPerLine = 0; - m_yScrollPixelsPerLine = 0; - m_xScrollingEnabled = TRUE; - m_yScrollingEnabled = TRUE; - m_xScrollPosition = 0; - m_yScrollPosition = 0; - m_xScrollLinesPerPage = 0; - m_yScrollLinesPerPage = 0; - m_targetWindow = (wxWindow*) NULL; - m_scaleX = 1.0; - m_scaleY = 1.0; - m_hasScrolling = TRUE; -} - -bool wxScrolledWindow::Create(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) -{ - Init(); - - if (!PreCreation( parent, pos, size ) || - !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) - { - wxFAIL_MSG( wxT("wxWindow creation failed") ); - return FALSE; - } - - m_insertCallback = wxInsertChildInScrolledWindow; - - m_targetWindow = this; - - m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); - GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); - - GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); - - GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) ); - scroll_class->scrollbar_spacing = 0; - - gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); - - m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) ); - m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) ); - - m_wxwindow = gtk_pizza_new(); - - gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); - - GtkPizza *pizza = GTK_PIZZA(m_wxwindow); - - if (HasFlag(wxRAISED_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT ); - } - else if (HasFlag(wxSUNKEN_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN ); - } - else if (HasFlag(wxSIMPLE_BORDER)) - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN ); - } - else - { - gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE ); - } - - GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); - m_acceptsFocus = TRUE; - - // I _really_ don't want scrollbars in the beginning - m_vAdjust->lower = 0.0; - m_vAdjust->upper = 1.0; - m_vAdjust->value = 0.0; - m_vAdjust->step_increment = 1.0; - m_vAdjust->page_increment = 2.0; - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); - m_hAdjust->lower = 0.0; - m_hAdjust->upper = 1.0; - m_hAdjust->value = 0.0; - m_hAdjust->step_increment = 1.0; - m_hAdjust->page_increment = 2.0; - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); - - // Handlers for new scrollbar values - GtkVConnectEvent(); - GtkHConnectEvent(); - - // these handlers block mouse events to any window during scrolling such as - // motion events and prevent GTK and wxWidgets from fighting over where the - // slider should be - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", - (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event", - (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event", - (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); - - gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event", - (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); - - gtk_widget_show( m_wxwindow ); - - if (m_parent) - m_parent->DoAddChild( this ); - - m_focusWidget = m_wxwindow; - - PostCreation(); - - Show( TRUE ); - - return TRUE; -} - // ---------------------------------------------------------------------------- -// setting scrolling parameters +// wxScrollHelper implementation // ---------------------------------------------------------------------------- -void wxScrolledWindow::DoSetVirtualSize( int x, int y ) -{ - wxPanel::DoSetVirtualSize( x, y ); - AdjustScrollbars(); - - if (GetAutoLayout()) - Layout(); -} - -// wxWindow's GetBestVirtualSize returns the actual window size, -// whereas we want to return the virtual size -wxSize wxScrolledWindow::GetBestVirtualSize() const -{ - wxSize clientSize( GetClientSize() ); - if (GetSizer()) - { - wxSize minSize( GetSizer()->CalcMin() ); - - return wxSize( wxMax( clientSize.x, minSize.x ), wxMax( clientSize.y, minSize.y ) ); - } - else - return clientSize; -} - -// return the size best suited for the current window -// (this isn't a virtual size, this is a sensible size for the window) -wxSize wxScrolledWindow::DoGetBestSize() const -{ - wxSize best; - - if ( GetSizer() ) - { - wxSize b = GetSizer()->GetMinSize(); - - // Only use the content to set the window size in the direction - // where there's no scrolling; otherwise we're going to get a huge - // window in the direction in which scrolling is enabled - int ppuX, ppuY; - GetScrollPixelsPerUnit(& ppuX, & ppuY); - - wxSize minSize; - if ( GetMinSize().IsFullySpecified() ) - minSize = GetMinSize(); - else - minSize = GetSize(); - - if (ppuX > 0) - b.x = minSize.x; - if (ppuY > 0) - b.y = minSize.y; - best = b; - } - else - return wxWindow::DoGetBestSize(); - - // Add any difference between size and client size - wxSize diff = GetSize() - GetClientSize(); - best.x += wxMax(0, diff.x); - best.y += wxMax(0, diff.y); - - return best; -} - -/* - * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) - * noUnitsX/noUnitsY: : no. units per scrollbar - */ -void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, - int noUnitsX, int noUnitsY, - int xPos, int yPos, bool noRefresh ) +void wxScrollHelperNative::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, + int noUnitsX, int noUnitsY, + int xPos, int yPos, + bool noRefresh) { int xs, ys; - GetViewStart (& xs, & ys); + GetViewStart(& xs, & ys); int old_x = m_xScrollPixelsPerLine * xs; int old_y = m_yScrollPixelsPerLine * ys; @@ -405,8 +50,8 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, m_xScrollPixelsPerLine = pixelsPerUnitX; m_yScrollPixelsPerLine = pixelsPerUnitY; - m_hAdjust->value = m_xScrollPosition = xPos; - m_vAdjust->value = m_yScrollPosition = yPos; + m_win->m_hAdjust->value = m_xScrollPosition = xPos; + m_win->m_vAdjust->value = m_yScrollPosition = yPos; // Setting hints here should arguably be deprecated, but without it // a sizer might override this manual scrollbar setting in old code. @@ -424,621 +69,113 @@ void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX, int pixelsPerUnitY, m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y ); } + + m_targetWindow->m_hasScrolling = pixelsPerUnitX || pixelsPerUnitY; } -void wxScrolledWindow::AdjustScrollbars() +void wxScrollHelperNative::DoAdjustScrollbar(GtkAdjustment *adj, + int pixelsPerLine, + int winSize, + int virtSize, + int *pos, + int *lines, + int *linesPerPage) { - int w, h; - int vw, vh; - - m_targetWindow->GetClientSize( &w, &h ); - m_targetWindow->GetVirtualSize( &vw, &vh ); - - if (m_xScrollPixelsPerLine == 0) + if ( pixelsPerLine == 0 ) { - m_hAdjust->upper = 1.0; - m_hAdjust->page_increment = 1.0; - m_hAdjust->page_size = 1.0; + adj->upper = 1.0; + adj->page_increment = 1.0; + adj->page_size = 1.0; } - else + else // we do have scrollbar { - m_hAdjust->upper = (vw+m_xScrollPixelsPerLine-1) / m_xScrollPixelsPerLine; - m_hAdjust->page_size = w / m_xScrollPixelsPerLine; - m_hAdjust->page_increment = w / m_xScrollPixelsPerLine; + adj->upper = (virtSize + pixelsPerLine - 1) / pixelsPerLine; + adj->page_size = winSize / pixelsPerLine; + adj->page_increment = winSize / pixelsPerLine; // Special case. When client and virtual size are very close but // the client is big enough, kill scrollbar. - if ((m_hAdjust->page_size < m_hAdjust->upper) && (w >= vw)) - m_hAdjust->page_size += 1.0; + if ((adj->page_size < adj->upper) && (winSize >= virtSize)) + adj->page_size += 1.0; // If the scrollbar hits the right side, move the window // right to keep it from over extending. - if ( !wxIsNullDouble(m_hAdjust->value) && - (m_hAdjust->value + m_hAdjust->page_size > m_hAdjust->upper) ) + if ( !wxIsNullDouble(adj->value) && + (adj->value + adj->page_size > adj->upper) ) { - m_hAdjust->value = m_hAdjust->upper - m_hAdjust->page_size; - if (m_hAdjust->value < 0.0) - m_hAdjust->value = 0.0; - - if (GetChildren().GetCount() == 0) - m_xScrollPosition = (int)m_hAdjust->value; // This is enough without child windows + adj->value = adj->upper - adj->page_size; + if (adj->value < 0.0) + adj->value = 0.0; + + if ( m_win->GetChildren().empty() ) + { + // This is enough without child windows + *pos = (int)adj->value; + } else - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); // Actually scroll window + { + // We need to actually scroll window + gtk_signal_emit_by_name( GTK_OBJECT(adj), "value_changed" ); + } } } - if (m_yScrollPixelsPerLine == 0) - { - m_vAdjust->upper = 1.0; - m_vAdjust->page_increment = 1.0; - m_vAdjust->page_size = 1.0; - } - else - { - m_vAdjust->upper = (vh+m_yScrollPixelsPerLine-1) / m_yScrollPixelsPerLine; - m_vAdjust->page_size = h / m_yScrollPixelsPerLine; - m_vAdjust->page_increment = h / m_yScrollPixelsPerLine; - - if ((m_vAdjust->page_size < m_vAdjust->upper) && (h >= vh)) - m_vAdjust->page_size += 1.0; - - if ( !wxIsNullDouble(m_vAdjust->value) && - (m_vAdjust->value + m_vAdjust->page_size > m_vAdjust->upper) ) - { - m_vAdjust->value = m_vAdjust->upper - m_vAdjust->page_size; - if (m_vAdjust->value < 0.0) - m_vAdjust->value = 0.0; - - if (GetChildren().GetCount() == 0) - m_yScrollPosition = (int)m_vAdjust->value; - else - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - } - } - - m_xScrollLinesPerPage = (int)(m_hAdjust->page_increment + 0.5); - m_yScrollLinesPerPage = (int)(m_vAdjust->page_increment + 0.5); - - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); -} - - -// ---------------------------------------------------------------------------- -// target window handling -// ---------------------------------------------------------------------------- - -void wxScrolledWindow::SetTargetWindow( wxWindow *target, bool WXUNUSED(pushEventHandler) ) -{ - wxASSERT_MSG( target, wxT("target window must not be NULL") ); - m_targetWindow = target; -} - -wxWindow *wxScrolledWindow::GetTargetWindow() const -{ - return m_targetWindow; -} - -// Override this function if you don't want to have wxScrolledWindow -// automatically change the origin according to the scroll position. -void wxScrolledWindow::DoPrepareDC(wxDC& dc) -{ - dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine, - -m_yScrollPosition * m_yScrollPixelsPerLine ); + *lines = (int)(adj->upper + 0.5); + *linesPerPage = (int)(adj->page_increment + 0.5); + gtk_signal_emit_by_name( GTK_OBJECT(adj), "changed" ); } -void wxScrolledWindow::SetScrollRate( int xstep, int ystep ) +void wxScrollHelperNative::AdjustScrollbars() { - int old_x = m_xScrollPixelsPerLine * m_xScrollPosition; - int old_y = m_yScrollPixelsPerLine * m_yScrollPosition; - - m_xScrollPixelsPerLine = xstep; - m_yScrollPixelsPerLine = ystep; - - int new_x = m_xScrollPixelsPerLine * m_xScrollPosition; - int new_y = m_yScrollPixelsPerLine * m_yScrollPosition; - - m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y ); - - AdjustScrollbars(); -} - -void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const -{ - if ( x_unit ) - *x_unit = m_xScrollPixelsPerLine; - if ( y_unit ) - *y_unit = m_yScrollPixelsPerLine; -} - -int wxScrolledWindow::GetScrollPageSize(int orient) const -{ - if ( orient == wxHORIZONTAL ) - return m_xScrollLinesPerPage; - else - return m_yScrollLinesPerPage; -} - -void wxScrolledWindow::SetScrollPageSize(int orient, int pageSize) -{ - if ( orient == wxHORIZONTAL ) - m_xScrollLinesPerPage = pageSize; - else - m_yScrollLinesPerPage = pageSize; -} - -void wxScrolledWindow::OnScroll(wxScrollWinEvent& event) -{ - int orient = event.GetOrientation(); - - int nScrollInc = CalcScrollInc(event); - if (nScrollInc == 0) return; - - if (orient == wxHORIZONTAL) - { - int newPos = m_xScrollPosition + nScrollInc; - SetScrollPos(wxHORIZONTAL, newPos, TRUE ); - } - else - { - int newPos = m_yScrollPosition + nScrollInc; - SetScrollPos(wxVERTICAL, newPos, TRUE ); - } - - if (orient == wxHORIZONTAL) - { - m_xScrollPosition += nScrollInc; - } - else - { - m_yScrollPosition += nScrollInc; - } - - if (orient == wxHORIZONTAL) - { - if (m_xScrollingEnabled) - m_targetWindow->ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, (const wxRect *) NULL); - else - m_targetWindow->Refresh(); - } - else - { - if (m_yScrollingEnabled) - m_targetWindow->ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, (const wxRect *) NULL); - else - m_targetWindow->Refresh(); - } -} - -void wxScrolledWindow::Scroll( int x_pos, int y_pos ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (((x_pos == -1) || (x_pos == m_xScrollPosition)) && - ((y_pos == -1) || (y_pos == m_yScrollPosition))) return; - - if ((x_pos != -1) && (m_xScrollPixelsPerLine)) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - if (x_pos > max) x_pos = max; - if (x_pos < 0) x_pos = 0; - - int old_x = m_xScrollPosition; - m_xScrollPosition = x_pos; - m_hAdjust->value = x_pos; - - m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 ); - - // Just update the scrollbar, don't send any wxWidgets event - GtkHDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); - GtkHConnectEvent(); - } - - if ((y_pos != -1) && (m_yScrollPixelsPerLine)) - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - if (y_pos > max) y_pos = max; - if (y_pos < 0) y_pos = 0; - - int old_y = m_yScrollPosition; - m_yScrollPosition = y_pos; - m_vAdjust->value = y_pos; - - m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine ); - - // Just update the scrollbar, don't send any wxWidgets event - GtkVDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - GtkVConnectEvent(); - } -} - -// TODO: [VH]Scroll functions should be combined - -void wxScrolledWindow::GtkVScroll( float value, unsigned int scroll_type ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (m_yScrollPixelsPerLine == 0) - return; - - int y_pos = (int)(value+0.5); - - if (y_pos == m_yScrollPosition) - return; - - wxEventType command = GtkScrollWinTypeToWx(scroll_type); - - wxScrollWinEvent event( command, y_pos, wxVERTICAL ); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent( event ); -} - -void wxScrolledWindow::GtkHScroll( float value, unsigned int scroll_type ) -{ - wxASSERT_MSG( m_targetWindow != 0, _T("No target window") ); - - if (m_xScrollPixelsPerLine == 0) - return; - - int x_pos = (int)(value+0.5); - - if (x_pos == m_xScrollPosition) - return; - - wxEventType command = GtkScrollWinTypeToWx(scroll_type); - - wxScrollWinEvent event( command, x_pos, wxHORIZONTAL ); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent( event ); -} - -void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll) -{ - m_xScrollingEnabled = x_scroll; - m_yScrollingEnabled = y_scroll; -} - -// Where the current view starts from -void wxScrolledWindow::GetViewStart (int *x, int *y) const -{ - if ( x ) - *x = m_xScrollPosition; - if ( y ) - *y = m_yScrollPosition; -} - -void wxScrolledWindow::DoCalcScrolledPosition(int x, int y, int *xx, int *yy) const -{ - int xs, ys; - GetViewStart (& xs, & ys); - - if ( xx ) - *xx = x - xs * m_xScrollPixelsPerLine; - if ( yy ) - *yy = y - ys * m_yScrollPixelsPerLine; -} - -void wxScrolledWindow::DoCalcUnscrolledPosition(int x, int y, int *xx, int *yy) const -{ - int xs, ys; - GetViewStart (& xs, & ys); - - if ( xx ) - *xx = x + xs * m_xScrollPixelsPerLine; - if ( yy ) - *yy = y + ys * m_yScrollPixelsPerLine; -} - -int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent& event) -{ - int pos = event.GetPosition(); - int orient = event.GetOrientation(); - - int nScrollInc = 0; - if (event.GetEventType() == wxEVT_SCROLLWIN_TOP) - { - if (orient == wxHORIZONTAL) - nScrollInc = - m_xScrollPosition; - else - nScrollInc = - m_yScrollPosition; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM) - { - if (orient == wxHORIZONTAL) - nScrollInc = GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine - m_xScrollPosition; - else - nScrollInc = GetVirtualSize().GetHeight() / m_yScrollPixelsPerLine - m_yScrollPosition; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) - { - nScrollInc = -1; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) - { - nScrollInc = 1; - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP) - { - if (orient == wxHORIZONTAL) - nScrollInc = -GetScrollPageSize(wxHORIZONTAL); - else - nScrollInc = -GetScrollPageSize(wxVERTICAL); - } else - if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN) - { - if (orient == wxHORIZONTAL) - nScrollInc = GetScrollPageSize(wxHORIZONTAL); - else - nScrollInc = GetScrollPageSize(wxVERTICAL); - } else - if ((event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) || - (event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE)) - { - if (orient == wxHORIZONTAL) - nScrollInc = pos - m_xScrollPosition; - else - nScrollInc = pos - m_yScrollPosition; - } - - if (orient == wxHORIZONTAL) - { - if (m_xScrollPixelsPerLine > 0) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if ( (m_xScrollPosition + nScrollInc) < 0 ) - nScrollInc = -m_xScrollPosition; // As -ve as we can go - else if ( (m_xScrollPosition + nScrollInc) > max ) - nScrollInc = max - m_xScrollPosition; // As +ve as we can go - } - else - m_targetWindow->Refresh(); - } - else - { - if (m_yScrollPixelsPerLine > 0) - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if ( (m_yScrollPosition + nScrollInc) < 0 ) - nScrollInc = -m_yScrollPosition; // As -ve as we can go - else if ( (m_yScrollPosition + nScrollInc) > max ) - nScrollInc = max - m_yScrollPosition; // As +ve as we can go - } - else - m_targetWindow->Refresh(); - } - - return nScrollInc; -} - -void wxScrolledWindow::SetScrollPos( int orient, int pos, bool refresh ) -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") ); - - if (orient == wxHORIZONTAL) - { - int max = (int)(m_hAdjust->upper - m_hAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if (pos > max) pos = 0; - if (pos < 0) pos = 0; - - if (pos == (int)(m_hAdjust->value+0.5)) return; - m_hAdjust->value = pos; - } - else - { - int max = (int)(m_vAdjust->upper - m_vAdjust->page_size + 0.5); - if (max < 0) max = 0; - - if (pos > max) pos = 0; - if (pos < 0) pos = 0; - - if (pos == (int)(m_vAdjust->value+0.5)) return; - m_vAdjust->value = pos; - } - - if (m_wxwindow->window) - { - if (orient == wxHORIZONTAL) - { - // Just update the scrollbar, don't send any wxWidgets event - GtkHDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" ); - GtkHConnectEvent(); - } - else - { - // Just update the scrollbar, don't send any wxWidgets event - GtkVDisconnectEvent(); - gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" ); - GtkVConnectEvent(); - } - } -} - -void wxScrolledWindow::GtkVConnectEvent() -{ - gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed", - (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this ); -} - -void wxScrolledWindow::GtkHConnectEvent() -{ - gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed", - (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this ); -} + int w, h; + int vw, vh; -void wxScrolledWindow::GtkHDisconnectEvent() -{ - gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust), - (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this ); -} + m_targetWindow->GetClientSize( &w, &h ); + m_targetWindow->GetVirtualSize( &vw, &vh ); -void wxScrolledWindow::GtkVDisconnectEvent() -{ - gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust), - (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this ); + DoAdjustScrollbar(m_win->m_hAdjust, m_xScrollPixelsPerLine, w, vw, + &m_xScrollPosition, &m_xScrollLines, &m_xScrollLinesPerPage); + DoAdjustScrollbar(m_win->m_vAdjust, m_yScrollPixelsPerLine, h, vh, + &m_yScrollPosition, &m_yScrollLines, &m_yScrollLinesPerPage); } -bool wxScrolledWindow::Layout() +void wxScrollHelperNative::DoScroll(int orient, + GtkAdjustment *adj, + int pos, + int pixelsPerLine, + int *posOld) { - if (GetSizer() && m_targetWindow == this) + if ( pos != -1 && pos != *posOld && pixelsPerLine ) { - // If we're the scroll target, take into account the - // virtual size and scrolled position of the window. + int max = (int)(adj->upper - adj->page_size + 0.5); + if (max < 0) + max = 0; + if (pos > max) + pos = max; + if (pos < 0) + pos = 0; - int x, y, w, h; - CalcScrolledPosition(0,0, &x,&y); - GetVirtualSize(&w, &h); - GetSizer()->SetDimension(x, y, w, h); - return TRUE; - } - else - return wxPanel::Layout(); // fall back to default for LayoutConstraints -} + adj->value = pos; -// ---------------------------------------------------------------------------- -// event handlers -// ---------------------------------------------------------------------------- + int diff = (*posOld - pos)*pixelsPerLine; + m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0, + orient == wxHORIZONTAL ? 0 : diff); -// Default OnSize resets scrollbars, if any -void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - if ( m_targetWindow->GetAutoLayout() ) - { - wxSize size = m_targetWindow->GetBestVirtualSize(); + *posOld = pos; - // This will call ::Layout() and ::AdjustScrollbars() - SetVirtualSize( size ); - } - else - { - AdjustScrollbars(); + m_win->GtkUpdateScrollbar(orient); } } -// This calls OnDraw, having adjusted the origin according to the current -// scroll position -void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) +void wxScrollHelperNative::Scroll( int x_pos, int y_pos ) { - wxPaintDC dc(this); - PrepareDC(dc); - - OnDraw(dc); -} - -// kbd handling: notice that we use OnChar() and not OnKeyDown() for -// compatibility here - if we used OnKeyDown(), the programs which process -// arrows themselves in their OnChar() would never get the message and like -// this they always have the priority -void wxScrolledWindow::OnChar(wxKeyEvent& event) -{ - int stx, sty, // view origin - szx, szy, // view size (total) - clix, cliy; // view size (on screen) - - GetViewStart(&stx, &sty); - GetClientSize(&clix, &cliy); - GetVirtualSize(&szx, &szy); - - if( m_xScrollPixelsPerLine ) - { - clix /= m_xScrollPixelsPerLine; - szx /= m_xScrollPixelsPerLine; - } - else - { - clix = 0; - szx = -1; - } - if( m_yScrollPixelsPerLine ) - { - cliy /= m_yScrollPixelsPerLine; - szy /= m_yScrollPixelsPerLine; - } - else - { - cliy = 0; - szy = -1; - } - - int xScrollOld = GetScrollPos(wxHORIZONTAL), - yScrollOld = GetScrollPos(wxVERTICAL); - - int dsty; - switch ( event.GetKeyCode() ) - { - case WXK_PAGEUP: - case WXK_PRIOR: - dsty = sty - (5 * cliy / 6); - Scroll(-1, (dsty == -1) ? 0 : dsty); - break; - - case WXK_PAGEDOWN: - case WXK_NEXT: - Scroll(-1, sty + (5 * cliy / 6)); - break; - - case WXK_HOME: - Scroll(0, event.ControlDown() ? 0 : -1); - break; - - case WXK_END: - Scroll(szx - clix, event.ControlDown() ? szy - cliy : -1); - break; - - case WXK_UP: - Scroll(-1, sty - 1); - break; - - case WXK_DOWN: - Scroll(-1, sty + 1); - break; + wxCHECK_RET( m_targetWindow != 0, _T("No target window") ); - case WXK_LEFT: - Scroll(stx - 1, -1); - break; - - case WXK_RIGHT: - Scroll(stx + 1, -1); - break; - - default: - // not for us - event.Skip(); - return; - } - - int xScroll = GetScrollPos(wxHORIZONTAL); - if ( xScroll != xScrollOld ) - { - wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, xScroll, - wxHORIZONTAL); - eventS.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventS); - } - - int yScroll = GetScrollPos(wxVERTICAL); - if ( yScroll != yScrollOld ) - { - wxScrollWinEvent eventS(wxEVT_SCROLLWIN_THUMBTRACK, yScroll, - wxVERTICAL); - eventS.SetEventObject(this); - GetEventHandler()->ProcessEvent(eventS); - } + DoScroll(wxHORIZONTAL, m_win->m_hAdjust, x_pos, m_xScrollPixelsPerLine, + &m_xScrollPosition); + DoScroll(wxVERTICAL, m_win->m_vAdjust, y_pos, m_yScrollPixelsPerLine, + &m_yScrollPosition); } - -// vi:sts=4:sw=4:et