1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/scrolwin.cpp 
   3 // Purpose:     wxScrolledWindow implementation 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "scrolwin.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  32 #include "wx/dcclient.h" 
  34 #include "wx/gtk/scrolwin.h" 
  38 #include "wx/gtk/win_gtk.h" 
  40 // ---------------------------------------------------------------------------- 
  42 // ---------------------------------------------------------------------------- 
  44 BEGIN_EVENT_TABLE(wxScrolledWindow
, wxPanel
) 
  45     EVT_SCROLLWIN(wxScrolledWindow::OnScroll
) 
  46     EVT_SIZE(wxScrolledWindow::OnSize
) 
  47     EVT_PAINT(wxScrolledWindow::OnPaint
) 
  48     EVT_CHAR(wxScrolledWindow::OnChar
) 
  51 IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow
, wxPanel
) 
  53 // ============================================================================ 
  55 // ============================================================================ 
  57 //----------------------------------------------------------------------------- 
  59 //----------------------------------------------------------------------------- 
  61 extern bool       g_blockEventsOnDrag
; 
  62 extern bool       g_blockEventsOnScroll
; 
  64 //----------------------------------------------------------------------------- 
  66 //----------------------------------------------------------------------------- 
  68 extern void wxapp_install_idle_handler(); 
  71 //----------------------------------------------------------------------------- 
  72 // "value_changed" from m_vAdjust 
  73 //----------------------------------------------------------------------------- 
  75 static void gtk_scrolled_window_vscroll_callback( GtkAdjustment 
*adjust
, wxScrolledWindow 
*win 
) 
  78         wxapp_install_idle_handler(); 
  80     if (g_blockEventsOnDrag
) return; 
  82     if (!win
->m_hasVMT
) return; 
  84     win
->GtkVScroll( adjust
->value 
); 
  87 //----------------------------------------------------------------------------- 
  88 // "value_changed" from m_hAdjust 
  89 //----------------------------------------------------------------------------- 
  91 static void gtk_scrolled_window_hscroll_callback( GtkAdjustment 
*adjust
, wxScrolledWindow 
*win 
) 
  94         wxapp_install_idle_handler(); 
  96     if (g_blockEventsOnDrag
) return; 
  97     if (!win
->m_hasVMT
) return; 
  99     win
->GtkHScroll( adjust
->value 
); 
 102 //----------------------------------------------------------------------------- 
 103 // "button_press_event" from scrollbar 
 104 //----------------------------------------------------------------------------- 
 106 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
 107                                                  GdkEventButton 
*gdk_event
, 
 111         wxapp_install_idle_handler(); 
 113     g_blockEventsOnScroll 
= TRUE
; 
 114     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
 119 //----------------------------------------------------------------------------- 
 120 // "button_release_event" from scrollbar 
 121 //----------------------------------------------------------------------------- 
 123 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
 124                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
 127 //  don't test here as we can release the mouse while being over 
 128 //  a different window than the slider 
 130 //    if (gdk_event->window != widget->slider) return FALSE; 
 132     g_blockEventsOnScroll 
= FALSE
; 
 134     if (win
->m_isScrolling
) 
 136         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
 140         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
 141         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
 143             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
 146         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
 148             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
 152         wxScrollWinEvent 
event( command
, value
, dir 
); 
 153         event
.SetEventObject( win 
); 
 154         win
->GetEventHandler()->ProcessEvent( event 
); 
 157     win
->m_isScrolling 
= FALSE
; 
 162 //----------------------------------------------------------------------------- 
 163 // InsertChild for wxScrolledWindow 
 164 //----------------------------------------------------------------------------- 
 166 static void wxInsertChildInScrolledWindow( wxWindow
* parent
, wxWindow
* child 
) 
 168     // The window might have been scrolled already, do we 
 169     // have to adapt the position. 
 170     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
 171     child
->m_x 
+= pizza
->xoffset
; 
 172     child
->m_y 
+= pizza
->yoffset
; 
 174     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
 175                      GTK_WIDGET(child
->m_widget
), 
 182 // ---------------------------------------------------------------------------- 
 183 // wxScrolledWindow creation 
 184 // ---------------------------------------------------------------------------- 
 186 void wxScrolledWindow::Init() 
 188     m_xScrollPixelsPerLine 
= 0; 
 189     m_yScrollPixelsPerLine 
= 0; 
 190     m_xScrollingEnabled 
= TRUE
; 
 191     m_yScrollingEnabled 
= TRUE
; 
 192     m_xScrollPosition 
= 0; 
 193     m_yScrollPosition 
= 0; 
 196     m_xScrollLinesPerPage 
= 0; 
 197     m_yScrollLinesPerPage 
= 0; 
 198     m_targetWindow 
= (wxWindow
*) NULL
; 
 201     m_hasScrolling 
= TRUE
; 
 204 bool wxScrolledWindow::Create(wxWindow 
*parent
, 
 209                               const wxString
& name
) 
 213     if (!PreCreation( parent
, pos
, size 
) || 
 214         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 216         wxFAIL_MSG( wxT("wxWindow creation failed") ); 
 220     m_insertCallback 
= wxInsertChildInScrolledWindow
; 
 222     m_targetWindow 
= this; 
 224     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
 225     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 227     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
 229     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
 230     scroll_class
->scrollbar_spacing 
= 0; 
 232     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
 234     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
 235     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
 237     m_wxwindow 
= gtk_pizza_new(); 
 239     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
 241     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
 243     if (HasFlag(wxRAISED_BORDER
)) 
 245         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
 247     else if (HasFlag(wxSUNKEN_BORDER
)) 
 249         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
 251     else if (HasFlag(wxSIMPLE_BORDER
)) 
 253         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
 257         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
 260     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 261     m_acceptsFocus 
= TRUE
; 
 263     // I _really_ don't want scrollbars in the beginning 
 264     m_vAdjust
->lower 
= 0.0; 
 265     m_vAdjust
->upper 
= 1.0; 
 266     m_vAdjust
->value 
= 0.0; 
 267     m_vAdjust
->step_increment 
= 1.0; 
 268     m_vAdjust
->page_increment 
= 1.0; 
 269     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 270     m_hAdjust
->lower 
= 0.0; 
 271     m_hAdjust
->upper 
= 1.0; 
 272     m_hAdjust
->value 
= 0.0; 
 273     m_hAdjust
->step_increment 
= 1.0; 
 274     m_hAdjust
->page_increment 
= 1.0; 
 275     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 277     // Handlers for new scrollbar values 
 281     // these handlers block mouse events to any window during scrolling such as 
 282     // motion events and prevent GTK and wxWindows from fighting over where the 
 285     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
 286           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 288     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
 289           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 291     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
 292           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 294     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
 295           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 297     gtk_widget_show( m_wxwindow 
); 
 300         m_parent
->DoAddChild( this ); 
 309 // ---------------------------------------------------------------------------- 
 310 // setting scrolling parameters 
 311 // ---------------------------------------------------------------------------- 
 314  * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) 
 315  * noUnitsX/noUnitsY:        : no. units per scrollbar 
 317 void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX
, int pixelsPerUnitY
, 
 318                int noUnitsX
, int noUnitsY
, 
 319                int xPos
, int yPos
, bool noRefresh 
) 
 321     int old_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 322     int old_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 324     m_xScrollPixelsPerLine 
= pixelsPerUnitX
; 
 325     m_yScrollPixelsPerLine 
= pixelsPerUnitY
; 
 326     m_xScrollLines 
= noUnitsX
; 
 327     m_yScrollLines 
= noUnitsY
; 
 328     m_xScrollPosition 
= xPos
; 
 329     m_yScrollPosition 
= yPos
; 
 331     m_hAdjust
->lower 
= 0.0; 
 332     m_hAdjust
->upper 
= noUnitsX
; 
 333     m_hAdjust
->value 
= xPos
; 
 334     m_hAdjust
->step_increment 
= 1.0; 
 335     m_hAdjust
->page_increment 
= 2.0; 
 337     m_vAdjust
->lower 
= 0.0; 
 338     m_vAdjust
->upper 
= noUnitsY
; 
 339     m_vAdjust
->value 
= yPos
; 
 340     m_vAdjust
->step_increment 
= 1.0; 
 341     m_vAdjust
->page_increment 
= 2.0; 
 347         int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 348         int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 350         m_targetWindow
->ScrollWindow( old_x
-new_x
, old_y
-new_y 
); 
 354 void wxScrolledWindow::AdjustScrollbars() 
 357     m_targetWindow
->GetClientSize( &w
, &h 
); 
 359     if (m_xScrollPixelsPerLine 
== 0) 
 360         m_hAdjust
->page_size 
= 1.0; 
 362         m_hAdjust
->page_size 
= (w 
/ m_xScrollPixelsPerLine
); 
 364     if (m_yScrollPixelsPerLine 
== 0) 
 365         m_vAdjust
->page_size 
= 1.0; 
 367         m_vAdjust
->page_size 
= (h 
/ m_yScrollPixelsPerLine
); 
 369     m_xScrollLinesPerPage 
= (int)(m_hAdjust
->page_size 
+ 0.5); 
 370     m_yScrollLinesPerPage 
= (int)(m_vAdjust
->page_size 
+ 0.5); 
 372     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 373     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 376 // ---------------------------------------------------------------------------- 
 377 // target window handling 
 378 // ---------------------------------------------------------------------------- 
 380 void wxScrolledWindow::SetTargetWindow( wxWindow 
*target 
) 
 382     wxASSERT_MSG( target
, wxT("target window must not be NULL") ); 
 383     m_targetWindow 
= target
; 
 386 wxWindow 
*wxScrolledWindow::GetTargetWindow() 
 388     return m_targetWindow
; 
 391 // Override this function if you don't want to have wxScrolledWindow 
 392 // automatically change the origin according to the scroll position. 
 393 void wxScrolledWindow::PrepareDC(wxDC
& dc
) 
 395     dc
.SetDeviceOrigin( -m_xScrollPosition 
* m_xScrollPixelsPerLine
, 
 396                         -m_yScrollPosition 
* m_yScrollPixelsPerLine 
); 
 399 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const 
 402         *x_unit 
= m_xScrollPixelsPerLine
; 
 404         *y_unit 
= m_yScrollPixelsPerLine
; 
 407 int wxScrolledWindow::GetScrollPageSize(int orient
) const 
 409     if ( orient 
== wxHORIZONTAL 
) 
 410         return m_xScrollLinesPerPage
; 
 412         return m_yScrollLinesPerPage
; 
 415 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
) 
 417     if ( orient 
== wxHORIZONTAL 
) 
 418         m_xScrollLinesPerPage 
= pageSize
; 
 420         m_yScrollLinesPerPage 
= pageSize
; 
 423 void wxScrolledWindow::OnScroll(wxScrollWinEvent
& event
) 
 425     int orient 
= event
.GetOrientation(); 
 427     int nScrollInc 
= CalcScrollInc(event
); 
 428     if (nScrollInc 
== 0) return; 
 430     if (orient 
== wxHORIZONTAL
) 
 432         int newPos 
= m_xScrollPosition 
+ nScrollInc
; 
 433         SetScrollPos(wxHORIZONTAL
, newPos
, TRUE 
); 
 437         int newPos 
= m_yScrollPosition 
+ nScrollInc
; 
 438         SetScrollPos(wxVERTICAL
, newPos
, TRUE 
); 
 441     if (orient 
== wxHORIZONTAL
) 
 443         m_xScrollPosition 
+= nScrollInc
; 
 447         m_yScrollPosition 
+= nScrollInc
; 
 450     if (orient 
== wxHORIZONTAL
) 
 452        if (m_xScrollingEnabled
) 
 453             m_targetWindow
->ScrollWindow(-m_xScrollPixelsPerLine 
* nScrollInc
, 0, (const wxRect 
*) NULL
); 
 455             m_targetWindow
->Refresh(); 
 459         if (m_yScrollingEnabled
) 
 460             m_targetWindow
->ScrollWindow(0, -m_yScrollPixelsPerLine 
* nScrollInc
, (const wxRect 
*) NULL
); 
 462             m_targetWindow
->Refresh(); 
 466 void wxScrolledWindow::Scroll( int x_pos
, int y_pos 
) 
 471     if (((x_pos 
== -1) || (x_pos 
== m_xScrollPosition
)) && 
 472         ((y_pos 
== -1) || (y_pos 
== m_yScrollPosition
))) return; 
 474     if ((x_pos 
!= -1) && (m_xScrollPixelsPerLine
)) 
 476         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 477         if (max 
< 0) max 
= 0; 
 478         if (x_pos 
> max
) x_pos 
= max
; 
 479         if (x_pos 
< 0) x_pos 
= 0; 
 481         int old_x 
= m_xScrollPosition
; 
 482         m_xScrollPosition 
= x_pos
; 
 483         m_hAdjust
->value 
= x_pos
; 
 485         m_targetWindow
->ScrollWindow( (old_x
-m_xScrollPosition
)*m_xScrollPixelsPerLine
, 0 ); 
 487         // Just update the scrollbar, don't send any wxWindows event 
 488         GtkHDisconnectEvent(); 
 489         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 493     if ((y_pos 
!= -1) && (m_yScrollPixelsPerLine
)) 
 495         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 496         if (max 
< 0) max 
= 0; 
 497         if (y_pos 
> max
) y_pos 
= max
; 
 498         if (y_pos 
< 0) y_pos 
= 0; 
 500         int old_y 
= m_yScrollPosition
; 
 501         m_yScrollPosition 
= y_pos
; 
 502         m_vAdjust
->value 
= y_pos
; 
 504         m_targetWindow
->ScrollWindow( 0, (old_y
-m_yScrollPosition
)*m_yScrollPixelsPerLine 
); 
 506         // Just update the scrollbar, don't send any wxWindows event 
 507         GtkVDisconnectEvent(); 
 508         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 513 void wxScrolledWindow::GtkVScroll( float value 
) 
 518     if (m_yScrollPixelsPerLine 
== 0) 
 521     int y_pos 
= (int)(value
+0.5); 
 523     if (y_pos 
== m_yScrollPosition
) 
 526     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
 527     GtkRange 
*range 
= GTK_RANGE(scrolledWindow
->vscrollbar
); 
 529     wxEventType command 
= wxEVT_SCROLLWIN_THUMBTRACK
; 
 530     if      (range
->scroll_type 
== GTK_SCROLL_STEP_BACKWARD
) command 
= wxEVT_SCROLLWIN_LINEUP
; 
 531     else if (range
->scroll_type 
== GTK_SCROLL_STEP_FORWARD
)  command 
= wxEVT_SCROLLWIN_LINEDOWN
; 
 532     else if (range
->scroll_type 
== GTK_SCROLL_PAGE_BACKWARD
) command 
= wxEVT_SCROLLWIN_PAGEUP
; 
 533     else if (range
->scroll_type 
== GTK_SCROLL_PAGE_FORWARD
)  command 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
 535     wxScrollWinEvent 
event( command
, y_pos
, wxVERTICAL 
); 
 536     event
.SetEventObject( this ); 
 537     GetEventHandler()->ProcessEvent( event 
); 
 540 void wxScrolledWindow::GtkHScroll( float value 
) 
 545     if (m_xScrollPixelsPerLine 
== 0) 
 548     int x_pos 
= (int)(value
+0.5); 
 550     if (x_pos 
== m_xScrollPosition
) 
 553     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
 554     GtkRange 
*range 
= GTK_RANGE(scrolledWindow
->hscrollbar
); 
 556     wxEventType command 
= wxEVT_SCROLLWIN_THUMBTRACK
; 
 557     if      (range
->scroll_type 
== GTK_SCROLL_STEP_BACKWARD
) command 
= wxEVT_SCROLLWIN_LINEUP
; 
 558     else if (range
->scroll_type 
== GTK_SCROLL_STEP_FORWARD
)  command 
= wxEVT_SCROLLWIN_LINEDOWN
; 
 559     else if (range
->scroll_type 
== GTK_SCROLL_PAGE_BACKWARD
) command 
= wxEVT_SCROLLWIN_PAGEUP
; 
 560     else if (range
->scroll_type 
== GTK_SCROLL_PAGE_FORWARD
)  command 
= wxEVT_SCROLLWIN_PAGEDOWN
; 
 562     wxScrollWinEvent 
event( command
, x_pos
, wxHORIZONTAL 
); 
 563     event
.SetEventObject( this ); 
 564     GetEventHandler()->ProcessEvent( event 
); 
 567 void wxScrolledWindow::EnableScrolling (bool x_scroll
, bool y_scroll
) 
 569     m_xScrollingEnabled 
= x_scroll
; 
 570     m_yScrollingEnabled 
= y_scroll
; 
 573 void wxScrolledWindow::GetVirtualSize (int *x
, int *y
) const 
 576         *x 
= m_xScrollPixelsPerLine 
* m_xScrollLines
; 
 578         *y 
= m_yScrollPixelsPerLine 
* m_yScrollLines
; 
 581 // Where the current view starts from 
 582 void wxScrolledWindow::GetViewStart (int *x
, int *y
) const 
 585         *x 
= m_xScrollPosition
; 
 587         *y 
= m_yScrollPosition
; 
 590 void wxScrolledWindow::CalcScrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 593         *xx 
= x 
- m_xScrollPosition 
* m_xScrollPixelsPerLine
; 
 595         *yy 
= y 
- m_yScrollPosition 
* m_yScrollPixelsPerLine
; 
 598 void wxScrolledWindow::CalcUnscrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 601         *xx 
= x 
+ m_xScrollPosition 
* m_xScrollPixelsPerLine
; 
 603         *yy 
= y 
+ m_yScrollPosition 
* m_yScrollPixelsPerLine
; 
 606 int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent
& event
) 
 608     int pos 
= event
.GetPosition(); 
 609     int orient 
= event
.GetOrientation(); 
 612     if (event
.GetEventType() == wxEVT_SCROLLWIN_TOP
) 
 614             if (orient 
== wxHORIZONTAL
) 
 615                 nScrollInc 
= - m_xScrollPosition
; 
 617                 nScrollInc 
= - m_yScrollPosition
; 
 619     if (event
.GetEventType() == wxEVT_SCROLLWIN_BOTTOM
) 
 621             if (orient 
== wxHORIZONTAL
) 
 622                 nScrollInc 
= m_xScrollLines 
- m_xScrollPosition
; 
 624                 nScrollInc 
= m_yScrollLines 
- m_yScrollPosition
; 
 626     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) 
 630     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) 
 634     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEUP
) 
 636             if (orient 
== wxHORIZONTAL
) 
 637                 nScrollInc 
= -GetScrollPageSize(wxHORIZONTAL
); 
 639                 nScrollInc 
= -GetScrollPageSize(wxVERTICAL
); 
 641     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN
) 
 643             if (orient 
== wxHORIZONTAL
) 
 644                 nScrollInc 
= GetScrollPageSize(wxHORIZONTAL
); 
 646                 nScrollInc 
= GetScrollPageSize(wxVERTICAL
); 
 648     if ((event
.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK
) || 
 649         (event
.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE
)) 
 651             if (orient 
== wxHORIZONTAL
) 
 652                 nScrollInc 
= pos 
- m_xScrollPosition
; 
 654                 nScrollInc 
= pos 
- m_yScrollPosition
; 
 657     if (orient 
== wxHORIZONTAL
) 
 659         if (m_xScrollPixelsPerLine 
> 0) 
 661             int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 662             if (max 
< 0) max 
= 0; 
 664             if ( (m_xScrollPosition 
+ nScrollInc
) < 0 ) 
 665                 nScrollInc 
= -m_xScrollPosition
; // As -ve as we can go 
 666             else if ( (m_xScrollPosition 
+ nScrollInc
) > max 
) 
 667                 nScrollInc 
= max 
- m_xScrollPosition
; // As +ve as we can go 
 670             m_targetWindow
->Refresh(); 
 674         if (m_yScrollPixelsPerLine 
> 0) 
 676             int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 677             if (max 
< 0) max 
= 0; 
 679             if ( (m_yScrollPosition 
+ nScrollInc
) < 0 ) 
 680                 nScrollInc 
= -m_yScrollPosition
; // As -ve as we can go 
 681             else if ( (m_yScrollPosition 
+ nScrollInc
) > max 
) 
 682                 nScrollInc 
= max 
- m_yScrollPosition
; // As +ve as we can go 
 685             m_targetWindow
->Refresh(); 
 691 void wxScrolledWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) ) 
 693     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
 695     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
 697     if (orient 
== wxHORIZONTAL
) 
 699         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 700         if (max 
< 0) max 
= 0; 
 702         if (pos 
> max
) pos 
= 0; 
 703         if (pos 
< 0) pos 
= 0; 
 705         if (pos 
== (int)(m_hAdjust
->value
+0.5)) return; 
 706         m_hAdjust
->value 
= pos
; 
 710         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 711         if (max 
< 0) max 
= 0; 
 713         if (pos 
> max
) pos 
= 0; 
 714         if (pos 
< 0) pos 
= 0; 
 716         if (pos 
== (int)(m_vAdjust
->value
+0.5)) return; 
 717         m_vAdjust
->value 
= pos
; 
 720     if (m_wxwindow
->window
) 
 722         if (orient 
== wxHORIZONTAL
) 
 724             // Just update the scrollbar, don't send any wxWindows event 
 725             GtkHDisconnectEvent(); 
 726             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 731             // Just update the scrollbar, don't send any wxWindows event 
 732             GtkVDisconnectEvent(); 
 733             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 739 void wxScrolledWindow::GtkVConnectEvent() 
 741     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
 742           (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 745 void wxScrolledWindow::GtkHConnectEvent() 
 747     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
 748           (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 751 void wxScrolledWindow::GtkHDisconnectEvent() 
 753     gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
 754         (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 757 void wxScrolledWindow::GtkVDisconnectEvent() 
 759     gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
 760         (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 763 // ---------------------------------------------------------------------------- 
 765 // ---------------------------------------------------------------------------- 
 767 // Default OnSize resets scrollbars, if any 
 768 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 770 #if wxUSE_CONSTRAINTS 
 778 // This calls OnDraw, having adjusted the origin according to the current 
 780 void wxScrolledWindow::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 788 // kbd handling: notice that we use OnChar() and not OnKeyDown() for 
 789 // compatibility here - if we used OnKeyDown(), the programs which process 
 790 // arrows themselves in their OnChar() would never get the message and like 
 791 // this they always have the priority 
 792 void wxScrolledWindow::OnChar(wxKeyEvent
& event
) 
 794     int stx
, sty
,       // view origin 
 795         szx
, szy
,       // view size (total) 
 796         clix
, cliy
;     // view size (on screen) 
 798     ViewStart(&stx
, &sty
); 
 799     GetClientSize(&clix
, &cliy
); 
 800     GetVirtualSize(&szx
, &szy
); 
 802     if( m_xScrollPixelsPerLine 
) 
 804         clix 
/= m_xScrollPixelsPerLine
; 
 805         szx 
/= m_xScrollPixelsPerLine
; 
 812     if( m_yScrollPixelsPerLine 
) 
 814         cliy 
/= m_yScrollPixelsPerLine
; 
 815         szy 
/= m_yScrollPixelsPerLine
; 
 823     int xScrollOld 
= GetScrollPos(wxHORIZONTAL
), 
 824         yScrollOld 
= GetScrollPos(wxVERTICAL
); 
 827     switch ( event
.KeyCode() ) 
 831             dsty 
= sty 
- (5 * cliy 
/ 6); 
 832             Scroll(-1, (dsty 
== -1) ? 0 : dsty
); 
 837             Scroll(-1, sty 
+ (5 * cliy 
/ 6)); 
 841             Scroll(0, event
.ControlDown() ? 0 : -1); 
 845             Scroll(szx 
- clix
, event
.ControlDown() ? szy 
- cliy 
: -1); 
 870     int xScroll 
= GetScrollPos(wxHORIZONTAL
); 
 871     if ( xScroll 
!= xScrollOld 
) 
 873         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, xScroll
, 
 875         event
.SetEventObject(this); 
 876         GetEventHandler()->ProcessEvent(event
); 
 879     int yScroll 
= GetScrollPos(wxVERTICAL
); 
 880     if ( yScroll 
!= yScrollOld 
) 
 882         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, yScroll
, 
 884         event
.SetEventObject(this); 
 885         GetEventHandler()->ProcessEvent(event
);