]> git.saurik.com Git - wxWidgets.git/commitdiff
wxScrolledWindow is now a native widget under GTK.
authorRobert Roebling <robert@roebling.de>
Sun, 29 Apr 2001 15:27:57 +0000 (15:27 +0000)
committerRobert Roebling <robert@roebling.de>
Sun, 29 Apr 2001 15:27:57 +0000 (15:27 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9928 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

distrib/msw/tmake/filelist.txt
include/wx/gtk/scrolwin.h [new file with mode: 0644]
include/wx/gtk1/scrolwin.h [new file with mode: 0644]
include/wx/scrolwin.h
src/generic/listctrl.cpp
src/gtk/files.lst
src/gtk/scrolwin.cpp [new file with mode: 0644]
src/gtk1/files.lst
src/gtk1/scrolwin.cpp [new file with mode: 0644]

index cab3542f6b343356beea6015db12b736ffe59cc7..88958d7bea6b9ffe7ee439876a1525a85d42e1d3 100644 (file)
@@ -90,7 +90,7 @@ prop.cpp      G
 propform.cpp   G
 proplist.cpp   G
 sashwin.cpp    G
-scrolwin.cpp   G
+scrolwin.cpp   G       R
 splash.cpp     G
 splitter.cpp   G
 statline.cpp   G       U,R,P
@@ -374,6 +374,7 @@ radiobox.cpp        R
 radiobut.cpp   R
 region.cpp     R
 scrolbar.cpp   R
+scrolwin.cpp   R
 settings.cpp   R
 slider.cpp     R
 spinbutt.cpp   R
@@ -806,6 +807,7 @@ radiobox.h  K
 radiobut.h     K
 region.h       K
 scrolbar.h     K
+scrolwin.h     K
 settings.h     K
 slider.h       K
 spinbutt.h     K
diff --git a/include/wx/gtk/scrolwin.h b/include/wx/gtk/scrolwin.h
new file mode 100644 (file)
index 0000000..f28f92c
--- /dev/null
@@ -0,0 +1,139 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/generic/scrolwin.h
+// Purpose:     wxScrolledWindow class
+// Author:      Robert Roebling
+// Modified by:
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_GTK_SCROLLWIN_H_
+#define _WX_GTK_SCROLLWIN_H_
+
+#ifdef __GNUG__
+    #pragma interface "scrolwin.h"
+#endif
+
+// ----------------------------------------------------------------------------
+// headers and constants
+// ----------------------------------------------------------------------------
+
+#include "wx/window.h"
+#include "wx/panel.h"
+
+WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
+
+// default scrolled window style
+#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL)
+
+// ----------------------------------------------------------------------------
+// wxScrolledWindow
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxScrolledWindow : public wxPanel
+{
+public:
+    wxScrolledWindow();
+    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);
+    }
+
+    ~wxScrolledWindow();
+
+    bool Create(wxWindow *parent,
+                wxWindowID id,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxScrolledWindowStyle,
+                const wxString& name = wxPanelNameStr);
+
+    // 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 );
+    virtual wxWindow *GetTargetWindow();
+
+    // 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
+    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, wxWindows 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;
+    // Compatibility
+    void ViewStart(int *x, int *y) const
+       { GetViewStart( x, y ); }
+
+    // Actual size in pixels when scrolling is taken into account
+    virtual void GetVirtualSize(int *x, int *y) const;
+
+    virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
+    virtual void CalcUnscrolledPosition(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.
+    virtual void PrepareDC(wxDC& dc);
+
+    // Adjust the scrollbars
+    virtual void AdjustScrollbars();
+    
+    // implementation from now on
+    void OnSize(wxSizeEvent& event);
+    void OnPaint(wxPaintEvent& event);
+    void OnChar(wxKeyEvent& event);
+    
+    void GtkVScroll( float value );
+    void GtkHScroll( float value );
+
+protected:
+    wxWindow             *m_targetWindow;
+    int                   m_xScrollPixelsPerLine;
+    int                   m_yScrollPixelsPerLine;
+    bool                  m_xScrollingEnabled;
+    bool                  m_yScrollingEnabled;
+    int                   m_xScrollPosition;
+    int                   m_yScrollPosition;
+    int                   m_xScrollLines;
+    int                   m_yScrollLines;
+    int                   m_xScrollLinesPerPage;
+    int                   m_yScrollLinesPerPage;
+
+private:
+    DECLARE_EVENT_TABLE()
+    DECLARE_ABSTRACT_CLASS(wxScrolledWindow)
+};
+
+#endif
+    // _WX_GTK_SCROLLWIN_H_
diff --git a/include/wx/gtk1/scrolwin.h b/include/wx/gtk1/scrolwin.h
new file mode 100644 (file)
index 0000000..f28f92c
--- /dev/null
@@ -0,0 +1,139 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/generic/scrolwin.h
+// Purpose:     wxScrolledWindow class
+// Author:      Robert Roebling
+// Modified by:
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_GTK_SCROLLWIN_H_
+#define _WX_GTK_SCROLLWIN_H_
+
+#ifdef __GNUG__
+    #pragma interface "scrolwin.h"
+#endif
+
+// ----------------------------------------------------------------------------
+// headers and constants
+// ----------------------------------------------------------------------------
+
+#include "wx/window.h"
+#include "wx/panel.h"
+
+WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
+
+// default scrolled window style
+#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL)
+
+// ----------------------------------------------------------------------------
+// wxScrolledWindow
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxScrolledWindow : public wxPanel
+{
+public:
+    wxScrolledWindow();
+    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);
+    }
+
+    ~wxScrolledWindow();
+
+    bool Create(wxWindow *parent,
+                wxWindowID id,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxScrolledWindowStyle,
+                const wxString& name = wxPanelNameStr);
+
+    // 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 );
+    virtual wxWindow *GetTargetWindow();
+
+    // 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
+    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, wxWindows 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;
+    // Compatibility
+    void ViewStart(int *x, int *y) const
+       { GetViewStart( x, y ); }
+
+    // Actual size in pixels when scrolling is taken into account
+    virtual void GetVirtualSize(int *x, int *y) const;
+
+    virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
+    virtual void CalcUnscrolledPosition(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.
+    virtual void PrepareDC(wxDC& dc);
+
+    // Adjust the scrollbars
+    virtual void AdjustScrollbars();
+    
+    // implementation from now on
+    void OnSize(wxSizeEvent& event);
+    void OnPaint(wxPaintEvent& event);
+    void OnChar(wxKeyEvent& event);
+    
+    void GtkVScroll( float value );
+    void GtkHScroll( float value );
+
+protected:
+    wxWindow             *m_targetWindow;
+    int                   m_xScrollPixelsPerLine;
+    int                   m_yScrollPixelsPerLine;
+    bool                  m_xScrollingEnabled;
+    bool                  m_yScrollingEnabled;
+    int                   m_xScrollPosition;
+    int                   m_yScrollPosition;
+    int                   m_xScrollLines;
+    int                   m_yScrollLines;
+    int                   m_xScrollLinesPerPage;
+    int                   m_yScrollLinesPerPage;
+
+private:
+    DECLARE_EVENT_TABLE()
+    DECLARE_ABSTRACT_CLASS(wxScrolledWindow)
+};
+
+#endif
+    // _WX_GTK_SCROLLWIN_H_
index 44298184bbe853c6cf678e38de4f4b0564d5d09d..86457a8b509c1e5c64df8da7aa8b0a49ea288b35 100644 (file)
@@ -1,7 +1,11 @@
 #ifndef _WX_SCROLWIN_H_BASE_
 #define _WX_SCROLWIN_H_BASE_
 
+#ifdef __WXGTK__
+#include "wx/gtk/scrolwin.h"
+#else
 #include "wx/generic/scrolwin.h"
+#endif
 
 #endif
     // _WX_SCROLWIN_H_BASE_
index 2f69514f230d433407e9efd33c63942c2042be17..c985d513469303914a5f3c446e2360ec5d9dfaf1 100644 (file)
@@ -3129,7 +3129,10 @@ void wxListMainWindow::SortItems( wxListCtrlCompare fn, long data )
 
 void wxListMainWindow::OnScroll(wxScrollWinEvent& event)
 {
-        wxScrolledWindow::OnScroll( event ) ;
+#ifndef __WXGTK__
+     wxScrolledWindow::OnScroll( event ) ;
+#endif
+
 #if wxUSE_GENERIC_LIST_EXTENSIONS
 
     if (event.GetOrientation() == wxHORIZONTAL && ( m_mode & wxLC_REPORT ))
index 9f1acd466981f735753907099df61d3cb80d9b55..e56c40a7f88ff6aee1782b296aef655c28ee964f 100644 (file)
@@ -31,7 +31,6 @@ ALL_SOURCES = \
                generic/propform.cpp \
                generic/proplist.cpp \
                generic/sashwin.cpp \
-               generic/scrolwin.cpp \
                generic/splash.cpp \
                generic/splitter.cpp \
                generic/statusbr.cpp \
@@ -190,6 +189,7 @@ ALL_SOURCES = \
                gtk/radiobut.cpp \
                gtk/region.cpp \
                gtk/scrolbar.cpp \
+               gtk/scrolwin.cpp \
                gtk/settings.cpp \
                gtk/slider.cpp \
                gtk/spinbutt.cpp \
diff --git a/src/gtk/scrolwin.cpp b/src/gtk/scrolwin.cpp
new file mode 100644 (file)
index 0000000..2d64124
--- /dev/null
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        generic/scrolwin.cpp
+// Purpose:     wxScrolledWindow implementation
+// Author:      Julian Smart
+// Modified by:
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart and Markus Holzem
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#ifdef __GNUG__
+    #pragma implementation "scrolwin.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#include "wx/utils.h"
+#include "wx/dcclient.h"
+
+#include "wx/gtk/scrolwin.h"
+#include "wx/panel.h"
+
+#include <gtk/gtk.h>
+#include "wx/gtk/win_gtk.h"
+
+// ----------------------------------------------------------------------------
+// event tables
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel)
+    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;
+
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_vAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (g_blockEventsOnDrag) return;
+
+    if (!win->m_hasVMT) return;
+
+    win->GtkVScroll( adjust->value );
+}
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_hAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (g_blockEventsOnDrag) return;
+    if (!win->m_hasVMT) return;
+
+    win->GtkHScroll( adjust->value );
+}
+
+//-----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+wxScrolledWindow::wxScrolledWindow()
+{
+    m_xScrollPixelsPerLine = 0;
+    m_yScrollPixelsPerLine = 0;
+    m_xScrollingEnabled = TRUE;
+    m_yScrollingEnabled = TRUE;
+    m_xScrollPosition = 0;
+    m_yScrollPosition = 0;
+    m_xScrollLines = 0;
+    m_yScrollLines = 0;
+    m_xScrollLinesPerPage = 0;
+    m_yScrollLinesPerPage = 0;
+    m_targetWindow = (wxWindow*) NULL;
+}
+
+bool wxScrolledWindow::Create(wxWindow *parent,
+                              wxWindowID id,
+                              const wxPoint& pos,
+                              const wxSize& size,
+                              long style,
+                              const wxString& name)
+{
+    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_xScrollPixelsPerLine = 0;
+    m_yScrollPixelsPerLine = 0;
+    m_xScrollingEnabled = TRUE;
+    m_yScrollingEnabled = TRUE;
+    m_xScrollPosition = 0;
+    m_yScrollPosition = 0;
+    m_xScrollLines = 0;
+    m_yScrollLines = 0;
+    m_xScrollLinesPerPage = 0;
+    m_yScrollLinesPerPage = 0;
+
+    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 = 1.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 = 1.0;
+    gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
+
+    // these handlers get notified when screen updates are required either when
+    // scrolling or when the window size (and therefore scrollbar configuration)
+    // has changed
+    gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
+          (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this );
+    gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
+          (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this );
+
+    gtk_widget_show( m_wxwindow );
+
+    if (m_parent)
+        m_parent->DoAddChild( this );
+
+    PostCreation();
+
+    Show( TRUE );
+
+    return TRUE;
+}
+
+wxScrolledWindow::~wxScrolledWindow()
+{
+}
+
+// ----------------------------------------------------------------------------
+// setting scrolling parameters
+// ----------------------------------------------------------------------------
+
+/*
+ * 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 )
+{
+    m_xScrollPixelsPerLine = pixelsPerUnitX;
+    m_yScrollPixelsPerLine = pixelsPerUnitY;
+    m_xScrollPosition = xPos;
+    m_yScrollPosition = yPos;
+    m_xScrollLines = noUnitsX;
+    m_yScrollLines = noUnitsY;
+    
+    m_hAdjust->lower = 0.0;
+    m_hAdjust->upper = noUnitsX;
+    m_hAdjust->value = xPos;
+    m_hAdjust->step_increment = 1.0;
+    m_hAdjust->page_increment = 1.0;
+
+    m_vAdjust->lower = 0.0;
+    m_vAdjust->upper = noUnitsY;
+    m_vAdjust->value = yPos;
+    m_vAdjust->step_increment = 1.0;
+    m_vAdjust->page_increment = 1.0;
+    
+    AdjustScrollbars();
+}
+
+void wxScrolledWindow::AdjustScrollbars()
+{
+    int w, h;
+    m_targetWindow->GetClientSize( &w, &h );
+    
+    if (m_xScrollPixelsPerLine == 0)
+        m_hAdjust->page_size = 1.0;
+    else
+        m_hAdjust->page_size = (w / m_xScrollPixelsPerLine);
+        
+    if (m_yScrollPixelsPerLine == 0)
+        m_vAdjust->page_size = 1.0;
+    else
+        m_vAdjust->page_size = (h / m_yScrollPixelsPerLine);
+    
+    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 )
+{
+    wxASSERT_MSG( target, wxT("target window must not be NULL") );
+    m_targetWindow = target;
+}
+
+wxWindow *wxScrolledWindow::GetTargetWindow()
+{
+    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::PrepareDC(wxDC& dc)
+{
+    dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine,
+                        -m_yScrollPosition * m_yScrollPixelsPerLine );
+}
+
+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;
+}
+
+/*
+ * Scroll to given position (scroll position, not pixel position)
+ */
+void wxScrolledWindow::Scroll( int x_pos, int y_pos )
+{
+    if (!m_targetWindow)
+        return;
+
+    if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
+        ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;
+
+    int w, h;
+    m_targetWindow->GetClientSize(&w, &h);
+
+    if ((x_pos != -1) && (m_xScrollPixelsPerLine))
+    {
+        int old_x = m_xScrollPosition;
+        m_xScrollPosition = x_pos;
+
+        // Calculate page size i.e. number of scroll units you get on the
+        // current client window
+        int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
+        if (noPagePositions < 1) noPagePositions = 1;
+
+        // Correct position if greater than extent of canvas minus
+        // the visible portion of it or if below zero
+        m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition );
+        m_xScrollPosition = wxMax( 0, m_xScrollPosition );
+
+        if (old_x != m_xScrollPosition) {
+            m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 );
+        }
+    }
+    if ((y_pos != -1) && (m_yScrollPixelsPerLine))
+    {
+        int old_y = m_yScrollPosition;
+        m_yScrollPosition = y_pos;
+
+        // Calculate page size i.e. number of scroll units you get on the
+        // current client window
+        int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
+        if (noPagePositions < 1) noPagePositions = 1;
+
+        // Correct position if greater than extent of canvas minus
+        // the visible portion of it or if below zero
+        m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
+        m_yScrollPosition = wxMax( 0, m_yScrollPosition );
+        
+        if (old_y != m_yScrollPosition) {
+            m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine );
+        }
+    }
+}
+
+void wxScrolledWindow::GtkVScroll( float value )
+{
+    Scroll( -1, (int)(value+0.5) );
+}
+
+void wxScrolledWindow::GtkHScroll( float value )
+{
+    Scroll( (int)(value+0.5), -1 );
+}
+
+void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll)
+{
+    m_xScrollingEnabled = x_scroll;
+    m_yScrollingEnabled = y_scroll;
+}
+
+void wxScrolledWindow::GetVirtualSize (int *x, int *y) const
+{
+    if ( x )
+        *x = m_xScrollPixelsPerLine * m_xScrollLines;
+    if ( y )
+        *y = m_yScrollPixelsPerLine * m_yScrollLines;
+}
+
+// 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::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
+{
+    if ( xx )
+        *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
+    if ( yy )
+        *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
+}
+
+void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
+{
+    if ( xx )
+        *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine;
+    if ( yy )
+        *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine;
+}
+
+// ----------------------------------------------------------------------------
+// event handlers
+// ----------------------------------------------------------------------------
+
+// Default OnSize resets scrollbars, if any
+void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+#if wxUSE_CONSTRAINTS
+    if (GetAutoLayout())
+        Layout();
+#endif
+
+    AdjustScrollbars();
+}
+
+// This calls OnDraw, having adjusted the origin according to the current
+// scroll position
+void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+    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)
+
+    ViewStart(&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 dsty;
+    switch ( event.KeyCode() )
+    {
+        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;
+
+        case WXK_LEFT:
+            Scroll(stx - 1, -1);
+            break;
+
+        case WXK_RIGHT:
+            Scroll(stx + 1, -1);
+            break;
+
+        default:
+            // not for us
+            event.Skip();
+    }
+}
index 9f1acd466981f735753907099df61d3cb80d9b55..e56c40a7f88ff6aee1782b296aef655c28ee964f 100644 (file)
@@ -31,7 +31,6 @@ ALL_SOURCES = \
                generic/propform.cpp \
                generic/proplist.cpp \
                generic/sashwin.cpp \
-               generic/scrolwin.cpp \
                generic/splash.cpp \
                generic/splitter.cpp \
                generic/statusbr.cpp \
@@ -190,6 +189,7 @@ ALL_SOURCES = \
                gtk/radiobut.cpp \
                gtk/region.cpp \
                gtk/scrolbar.cpp \
+               gtk/scrolwin.cpp \
                gtk/settings.cpp \
                gtk/slider.cpp \
                gtk/spinbutt.cpp \
diff --git a/src/gtk1/scrolwin.cpp b/src/gtk1/scrolwin.cpp
new file mode 100644 (file)
index 0000000..2d64124
--- /dev/null
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        generic/scrolwin.cpp
+// Purpose:     wxScrolledWindow implementation
+// Author:      Julian Smart
+// Modified by:
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Julian Smart and Markus Holzem
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#ifdef __GNUG__
+    #pragma implementation "scrolwin.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#include "wx/utils.h"
+#include "wx/dcclient.h"
+
+#include "wx/gtk/scrolwin.h"
+#include "wx/panel.h"
+
+#include <gtk/gtk.h>
+#include "wx/gtk/win_gtk.h"
+
+// ----------------------------------------------------------------------------
+// event tables
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxScrolledWindow, wxPanel)
+    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;
+
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_vAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_scrolled_window_vscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (g_blockEventsOnDrag) return;
+
+    if (!win->m_hasVMT) return;
+
+    win->GtkVScroll( adjust->value );
+}
+
+//-----------------------------------------------------------------------------
+// "value_changed" from m_hAdjust
+//-----------------------------------------------------------------------------
+
+static void gtk_scrolled_window_hscroll_callback( GtkAdjustment *adjust, wxScrolledWindow *win )
+{
+    if (g_isIdle)
+        wxapp_install_idle_handler();
+
+    if (g_blockEventsOnDrag) return;
+    if (!win->m_hasVMT) return;
+
+    win->GtkHScroll( adjust->value );
+}
+
+//-----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+wxScrolledWindow::wxScrolledWindow()
+{
+    m_xScrollPixelsPerLine = 0;
+    m_yScrollPixelsPerLine = 0;
+    m_xScrollingEnabled = TRUE;
+    m_yScrollingEnabled = TRUE;
+    m_xScrollPosition = 0;
+    m_yScrollPosition = 0;
+    m_xScrollLines = 0;
+    m_yScrollLines = 0;
+    m_xScrollLinesPerPage = 0;
+    m_yScrollLinesPerPage = 0;
+    m_targetWindow = (wxWindow*) NULL;
+}
+
+bool wxScrolledWindow::Create(wxWindow *parent,
+                              wxWindowID id,
+                              const wxPoint& pos,
+                              const wxSize& size,
+                              long style,
+                              const wxString& name)
+{
+    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_xScrollPixelsPerLine = 0;
+    m_yScrollPixelsPerLine = 0;
+    m_xScrollingEnabled = TRUE;
+    m_yScrollingEnabled = TRUE;
+    m_xScrollPosition = 0;
+    m_yScrollPosition = 0;
+    m_xScrollLines = 0;
+    m_yScrollLines = 0;
+    m_xScrollLinesPerPage = 0;
+    m_yScrollLinesPerPage = 0;
+
+    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 = 1.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 = 1.0;
+    gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
+
+    // these handlers get notified when screen updates are required either when
+    // scrolling or when the window size (and therefore scrollbar configuration)
+    // has changed
+    gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
+          (GtkSignalFunc) gtk_scrolled_window_hscroll_callback, (gpointer) this );
+    gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
+          (GtkSignalFunc) gtk_scrolled_window_vscroll_callback, (gpointer) this );
+
+    gtk_widget_show( m_wxwindow );
+
+    if (m_parent)
+        m_parent->DoAddChild( this );
+
+    PostCreation();
+
+    Show( TRUE );
+
+    return TRUE;
+}
+
+wxScrolledWindow::~wxScrolledWindow()
+{
+}
+
+// ----------------------------------------------------------------------------
+// setting scrolling parameters
+// ----------------------------------------------------------------------------
+
+/*
+ * 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 )
+{
+    m_xScrollPixelsPerLine = pixelsPerUnitX;
+    m_yScrollPixelsPerLine = pixelsPerUnitY;
+    m_xScrollPosition = xPos;
+    m_yScrollPosition = yPos;
+    m_xScrollLines = noUnitsX;
+    m_yScrollLines = noUnitsY;
+    
+    m_hAdjust->lower = 0.0;
+    m_hAdjust->upper = noUnitsX;
+    m_hAdjust->value = xPos;
+    m_hAdjust->step_increment = 1.0;
+    m_hAdjust->page_increment = 1.0;
+
+    m_vAdjust->lower = 0.0;
+    m_vAdjust->upper = noUnitsY;
+    m_vAdjust->value = yPos;
+    m_vAdjust->step_increment = 1.0;
+    m_vAdjust->page_increment = 1.0;
+    
+    AdjustScrollbars();
+}
+
+void wxScrolledWindow::AdjustScrollbars()
+{
+    int w, h;
+    m_targetWindow->GetClientSize( &w, &h );
+    
+    if (m_xScrollPixelsPerLine == 0)
+        m_hAdjust->page_size = 1.0;
+    else
+        m_hAdjust->page_size = (w / m_xScrollPixelsPerLine);
+        
+    if (m_yScrollPixelsPerLine == 0)
+        m_vAdjust->page_size = 1.0;
+    else
+        m_vAdjust->page_size = (h / m_yScrollPixelsPerLine);
+    
+    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 )
+{
+    wxASSERT_MSG( target, wxT("target window must not be NULL") );
+    m_targetWindow = target;
+}
+
+wxWindow *wxScrolledWindow::GetTargetWindow()
+{
+    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::PrepareDC(wxDC& dc)
+{
+    dc.SetDeviceOrigin( -m_xScrollPosition * m_xScrollPixelsPerLine,
+                        -m_yScrollPosition * m_yScrollPixelsPerLine );
+}
+
+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;
+}
+
+/*
+ * Scroll to given position (scroll position, not pixel position)
+ */
+void wxScrolledWindow::Scroll( int x_pos, int y_pos )
+{
+    if (!m_targetWindow)
+        return;
+
+    if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
+        ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;
+
+    int w, h;
+    m_targetWindow->GetClientSize(&w, &h);
+
+    if ((x_pos != -1) && (m_xScrollPixelsPerLine))
+    {
+        int old_x = m_xScrollPosition;
+        m_xScrollPosition = x_pos;
+
+        // Calculate page size i.e. number of scroll units you get on the
+        // current client window
+        int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
+        if (noPagePositions < 1) noPagePositions = 1;
+
+        // Correct position if greater than extent of canvas minus
+        // the visible portion of it or if below zero
+        m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition );
+        m_xScrollPosition = wxMax( 0, m_xScrollPosition );
+
+        if (old_x != m_xScrollPosition) {
+            m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0 );
+        }
+    }
+    if ((y_pos != -1) && (m_yScrollPixelsPerLine))
+    {
+        int old_y = m_yScrollPosition;
+        m_yScrollPosition = y_pos;
+
+        // Calculate page size i.e. number of scroll units you get on the
+        // current client window
+        int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
+        if (noPagePositions < 1) noPagePositions = 1;
+
+        // Correct position if greater than extent of canvas minus
+        // the visible portion of it or if below zero
+        m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
+        m_yScrollPosition = wxMax( 0, m_yScrollPosition );
+        
+        if (old_y != m_yScrollPosition) {
+            m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine );
+        }
+    }
+}
+
+void wxScrolledWindow::GtkVScroll( float value )
+{
+    Scroll( -1, (int)(value+0.5) );
+}
+
+void wxScrolledWindow::GtkHScroll( float value )
+{
+    Scroll( (int)(value+0.5), -1 );
+}
+
+void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll)
+{
+    m_xScrollingEnabled = x_scroll;
+    m_yScrollingEnabled = y_scroll;
+}
+
+void wxScrolledWindow::GetVirtualSize (int *x, int *y) const
+{
+    if ( x )
+        *x = m_xScrollPixelsPerLine * m_xScrollLines;
+    if ( y )
+        *y = m_yScrollPixelsPerLine * m_yScrollLines;
+}
+
+// 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::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
+{
+    if ( xx )
+        *xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
+    if ( yy )
+        *yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
+}
+
+void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
+{
+    if ( xx )
+        *xx = x + m_xScrollPosition * m_xScrollPixelsPerLine;
+    if ( yy )
+        *yy = y + m_yScrollPosition * m_yScrollPixelsPerLine;
+}
+
+// ----------------------------------------------------------------------------
+// event handlers
+// ----------------------------------------------------------------------------
+
+// Default OnSize resets scrollbars, if any
+void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+#if wxUSE_CONSTRAINTS
+    if (GetAutoLayout())
+        Layout();
+#endif
+
+    AdjustScrollbars();
+}
+
+// This calls OnDraw, having adjusted the origin according to the current
+// scroll position
+void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+    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)
+
+    ViewStart(&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 dsty;
+    switch ( event.KeyCode() )
+    {
+        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;
+
+        case WXK_LEFT:
+            Scroll(stx - 1, -1);
+            break;
+
+        case WXK_RIGHT:
+            Scroll(stx + 1, -1);
+            break;
+
+        default:
+            // not for us
+            event.Skip();
+    }
+}