1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/scrolwin.cpp 
   3 // Purpose:     wxScrolledWindow implementation 
   4 // Author:      Robert Roebling 
   5 // Modified by: Ron Lee 
   8 // Copyright:   (c) Robert Roebling 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "scrolwin.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #include "wx/scrolwin.h" 
  33 #include "wx/dcclient.h" 
  37 #include "wx/gtk/private.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
, 
  77                                                   wxScrolledWindow 
*win 
) 
  80         wxapp_install_idle_handler(); 
  82     if (g_blockEventsOnDrag
) return; 
  84     if (!win
->m_hasVMT
) return; 
  86     win
->GtkVScroll( adjust
->value
, 
  87             GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win
->m_widget
)->vscrollbar
) ); 
  90 //----------------------------------------------------------------------------- 
  91 // "value_changed" from m_hAdjust 
  92 //----------------------------------------------------------------------------- 
  94 static void gtk_scrolled_window_hscroll_callback( GtkAdjustment 
*adjust
, 
  96                                                   wxScrolledWindow 
*win 
) 
  99         wxapp_install_idle_handler(); 
 101     if (g_blockEventsOnDrag
) return; 
 102     if (!win
->m_hasVMT
) return; 
 104     win
->GtkHScroll( adjust
->value
, 
 105             GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win
->m_widget
)->hscrollbar
) ); 
 108 //----------------------------------------------------------------------------- 
 109 // "button_press_event" from scrollbar 
 110 //----------------------------------------------------------------------------- 
 112 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
 113                                                  GdkEventButton 
*gdk_event
, 
 117         wxapp_install_idle_handler(); 
 119     g_blockEventsOnScroll 
= TRUE
; 
 121     // FIXME: there is no slider field any more, what was meant here? 
 123     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
 129 //----------------------------------------------------------------------------- 
 130 // "button_release_event" from scrollbar 
 131 //----------------------------------------------------------------------------- 
 133 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
 134                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
 137 //  don't test here as we can release the mouse while being over 
 138 //  a different window than the slider 
 140 //    if (gdk_event->window != widget->slider) return FALSE; 
 142     g_blockEventsOnScroll 
= FALSE
; 
 144     if (win
->m_isScrolling
) 
 146         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
 150         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
 151         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
 153             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
 156         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
 158             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
 162         wxScrollWinEvent 
event( command
, value
, dir 
); 
 163         event
.SetEventObject( win 
); 
 164         win
->GetEventHandler()->ProcessEvent( event 
); 
 167     win
->m_isScrolling 
= FALSE
; 
 172 //----------------------------------------------------------------------------- 
 173 // InsertChild for wxScrolledWindow 
 174 //----------------------------------------------------------------------------- 
 176 static void wxInsertChildInScrolledWindow( wxWindow
* parent
, wxWindow
* child 
) 
 178     // The window might have been scrolled already, do we 
 179     // have to adapt the position. 
 180     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
 181     child
->m_x 
+= pizza
->xoffset
; 
 182     child
->m_y 
+= pizza
->yoffset
; 
 184     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
 185                      GTK_WIDGET(child
->m_widget
), 
 192 // ---------------------------------------------------------------------------- 
 193 // wxScrolledWindow creation 
 194 // ---------------------------------------------------------------------------- 
 196 void wxScrolledWindow::Init() 
 198     m_xScrollPixelsPerLine 
= 0; 
 199     m_yScrollPixelsPerLine 
= 0; 
 200     m_xScrollingEnabled 
= TRUE
; 
 201     m_yScrollingEnabled 
= TRUE
; 
 202     m_xScrollPosition 
= 0; 
 203     m_yScrollPosition 
= 0; 
 204     m_xScrollLinesPerPage 
= 0; 
 205     m_yScrollLinesPerPage 
= 0; 
 206     m_targetWindow 
= (wxWindow
*) NULL
; 
 209     m_hasScrolling 
= TRUE
; 
 212 bool wxScrolledWindow::Create(wxWindow 
*parent
, 
 217                               const wxString
& name
) 
 221     if (!PreCreation( parent
, pos
, size 
) || 
 222         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 224         wxFAIL_MSG( wxT("wxWindow creation failed") ); 
 228     m_insertCallback 
= wxInsertChildInScrolledWindow
; 
 230     m_targetWindow 
= this; 
 232     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
 233     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 235     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
 237     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
 238     scroll_class
->scrollbar_spacing 
= 0; 
 240     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
 242     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
 243     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
 245     m_wxwindow 
= gtk_pizza_new(); 
 247     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
 249     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
 251     if (HasFlag(wxRAISED_BORDER
)) 
 253         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
 255     else if (HasFlag(wxSUNKEN_BORDER
)) 
 257         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
 259     else if (HasFlag(wxSIMPLE_BORDER
)) 
 261         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
 265         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
 268     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 269     m_acceptsFocus 
= TRUE
; 
 271     // I _really_ don't want scrollbars in the beginning 
 272     m_vAdjust
->lower 
= 0.0; 
 273     m_vAdjust
->upper 
= 1.0; 
 274     m_vAdjust
->value 
= 0.0; 
 275     m_vAdjust
->step_increment 
= 1.0; 
 276     m_vAdjust
->page_increment 
= 2.0; 
 277     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 278     m_hAdjust
->lower 
= 0.0; 
 279     m_hAdjust
->upper 
= 1.0; 
 280     m_hAdjust
->value 
= 0.0; 
 281     m_hAdjust
->step_increment 
= 1.0; 
 282     m_hAdjust
->page_increment 
= 2.0; 
 283     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 285     // Handlers for new scrollbar values 
 289     // these handlers block mouse events to any window during scrolling such as 
 290     // motion events and prevent GTK and wxWidgets from fighting over where the 
 293     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
 294           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 296     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
 297           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 299     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
 300           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 302     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
 303           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 305     gtk_widget_show( m_wxwindow 
); 
 308         m_parent
->DoAddChild( this ); 
 310     m_focusWidget 
= m_wxwindow
; 
 319 // ---------------------------------------------------------------------------- 
 320 // setting scrolling parameters 
 321 // ---------------------------------------------------------------------------- 
 323 void wxScrolledWindow::DoSetVirtualSize( int x
, int y 
) 
 325     wxPanel::DoSetVirtualSize( x
, y 
); 
 328 #if wxUSE_CONSTRAINTS 
 335  * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) 
 336  * noUnitsX/noUnitsY:        : no. units per scrollbar 
 338 void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX
, int pixelsPerUnitY
, 
 339                                       int noUnitsX
, int noUnitsY
, 
 340                                       int xPos
, int yPos
, bool noRefresh 
) 
 343     GetViewStart (& xs
, & ys
); 
 345     int old_x 
= m_xScrollPixelsPerLine 
* xs
; 
 346     int old_y 
= m_yScrollPixelsPerLine 
* ys
; 
 348     m_xScrollPixelsPerLine 
= pixelsPerUnitX
; 
 349     m_yScrollPixelsPerLine 
= pixelsPerUnitY
; 
 351     m_hAdjust
->value 
= m_xScrollPosition 
= xPos
; 
 352     m_vAdjust
->value 
= m_yScrollPosition 
= yPos
; 
 354     // Setting hints here should arguably be deprecated, but without it 
 355     // a sizer might override this manual scrollbar setting in old code. 
 356     m_targetWindow
->SetVirtualSizeHints( noUnitsX 
* pixelsPerUnitX
, noUnitsY 
* pixelsPerUnitY 
); 
 358     m_targetWindow
->SetVirtualSize( noUnitsX 
* pixelsPerUnitX
, noUnitsY 
* pixelsPerUnitY 
); 
 362         int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 363         int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 365         m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 369 void wxScrolledWindow::AdjustScrollbars() 
 374     m_targetWindow
->GetClientSize( &w
, &h 
); 
 375     m_targetWindow
->GetVirtualSize( &vw
, &vh 
); 
 377     if (m_xScrollPixelsPerLine 
== 0) 
 379         m_hAdjust
->upper 
= 1.0; 
 380         m_hAdjust
->page_increment 
= 1.0; 
 381         m_hAdjust
->page_size 
= 1.0; 
 385         m_hAdjust
->upper 
= vw 
/ m_xScrollPixelsPerLine
; 
 386         m_hAdjust
->page_increment 
= (w 
/ m_xScrollPixelsPerLine
); 
 387         m_hAdjust
->page_size 
= m_hAdjust
->page_increment
; 
 389         // If the scrollbar hits the right side, move the window 
 390         // right to keep it from over extending. 
 392         if ((m_hAdjust
->value 
!= 0.0) && (m_hAdjust
->value 
+ m_hAdjust
->page_size 
> m_hAdjust
->upper
)) 
 394             m_hAdjust
->value 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
 395             if (m_hAdjust
->value 
< 0.0) 
 396                 m_hAdjust
->value 
= 0.0; 
 398             if (GetChildren().GetCount() == 0) 
 399                 m_xScrollPosition 
= (int)m_hAdjust
->value
; // This is enough without child windows 
 401                 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); // Actually scroll window 
 405     if (m_yScrollPixelsPerLine 
== 0) 
 407         m_vAdjust
->upper 
= 1.0; 
 408         m_vAdjust
->page_increment 
= 1.0; 
 409         m_vAdjust
->page_size 
= 1.0; 
 413         m_vAdjust
->upper 
= vh 
/ m_yScrollPixelsPerLine
; 
 414         m_vAdjust
->page_increment 
= (h 
/ m_yScrollPixelsPerLine
); 
 415         m_vAdjust
->page_size 
= m_vAdjust
->page_increment
; 
 417         if ((m_vAdjust
->value 
!= 0.0) && (m_vAdjust
->value 
+ m_vAdjust
->page_size 
> m_vAdjust
->upper
)) 
 419             m_vAdjust
->value 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
 420             if (m_vAdjust
->value 
< 0.0) 
 421                 m_vAdjust
->value 
= 0.0; 
 423             if (GetChildren().GetCount() == 0) 
 424                 m_yScrollPosition 
= (int)m_vAdjust
->value
;   
 426                 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 430     m_xScrollLinesPerPage 
= (int)(m_hAdjust
->page_increment 
+ 0.5); 
 431     m_yScrollLinesPerPage 
= (int)(m_vAdjust
->page_increment 
+ 0.5); 
 433     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 434     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 438 // ---------------------------------------------------------------------------- 
 439 // target window handling 
 440 // ---------------------------------------------------------------------------- 
 442 void wxScrolledWindow::SetTargetWindow( wxWindow 
*target
, bool WXUNUSED(pushEventHandler
) ) 
 444     wxASSERT_MSG( target
, wxT("target window must not be NULL") ); 
 445     m_targetWindow 
= target
; 
 448 wxWindow 
*wxScrolledWindow::GetTargetWindow() const 
 450     return m_targetWindow
; 
 453 // Override this function if you don't want to have wxScrolledWindow 
 454 // automatically change the origin according to the scroll position. 
 455 void wxScrolledWindow::DoPrepareDC(wxDC
& dc
) 
 457     dc
.SetDeviceOrigin( -m_xScrollPosition 
* m_xScrollPixelsPerLine
, 
 458                         -m_yScrollPosition 
* m_yScrollPixelsPerLine 
); 
 461 void wxScrolledWindow::SetScrollRate( int xstep
, int ystep 
) 
 463     int old_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 464     int old_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 466     m_xScrollPixelsPerLine 
= xstep
; 
 467     m_yScrollPixelsPerLine 
= ystep
; 
 469     int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 470     int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 472     m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 477 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const 
 480         *x_unit 
= m_xScrollPixelsPerLine
; 
 482         *y_unit 
= m_yScrollPixelsPerLine
; 
 485 int wxScrolledWindow::GetScrollPageSize(int orient
) const 
 487     if ( orient 
== wxHORIZONTAL 
) 
 488         return m_xScrollLinesPerPage
; 
 490         return m_yScrollLinesPerPage
; 
 493 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
) 
 495     if ( orient 
== wxHORIZONTAL 
) 
 496         m_xScrollLinesPerPage 
= pageSize
; 
 498         m_yScrollLinesPerPage 
= pageSize
; 
 501 void wxScrolledWindow::OnScroll(wxScrollWinEvent
& event
) 
 503     int orient 
= event
.GetOrientation(); 
 505     int nScrollInc 
= CalcScrollInc(event
); 
 506     if (nScrollInc 
== 0) return; 
 508     if (orient 
== wxHORIZONTAL
) 
 510         int newPos 
= m_xScrollPosition 
+ nScrollInc
; 
 511         SetScrollPos(wxHORIZONTAL
, newPos
, TRUE 
); 
 515         int newPos 
= m_yScrollPosition 
+ nScrollInc
; 
 516         SetScrollPos(wxVERTICAL
, newPos
, TRUE 
); 
 519     if (orient 
== wxHORIZONTAL
) 
 521         m_xScrollPosition 
+= nScrollInc
; 
 525         m_yScrollPosition 
+= nScrollInc
; 
 528     if (orient 
== wxHORIZONTAL
) 
 530        if (m_xScrollingEnabled
) 
 531             m_targetWindow
->ScrollWindow(-m_xScrollPixelsPerLine 
* nScrollInc
, 0, (const wxRect 
*) NULL
); 
 533             m_targetWindow
->Refresh(); 
 537         if (m_yScrollingEnabled
) 
 538             m_targetWindow
->ScrollWindow(0, -m_yScrollPixelsPerLine 
* nScrollInc
, (const wxRect 
*) NULL
); 
 540             m_targetWindow
->Refresh(); 
 544 void wxScrolledWindow::Scroll( int x_pos
, int y_pos 
) 
 546     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 548     if (((x_pos 
== -1) || (x_pos 
== m_xScrollPosition
)) && 
 549         ((y_pos 
== -1) || (y_pos 
== m_yScrollPosition
))) return; 
 551     if ((x_pos 
!= -1) && (m_xScrollPixelsPerLine
)) 
 553         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 554         if (max 
< 0) max 
= 0; 
 555         if (x_pos 
> max
) x_pos 
= max
; 
 556         if (x_pos 
< 0) x_pos 
= 0; 
 558         int old_x 
= m_xScrollPosition
; 
 559         m_xScrollPosition 
= x_pos
; 
 560         m_hAdjust
->value 
= x_pos
; 
 562         m_targetWindow
->ScrollWindow( (old_x
-m_xScrollPosition
)*m_xScrollPixelsPerLine
, 0 ); 
 564         // Just update the scrollbar, don't send any wxWidgets event 
 565         GtkHDisconnectEvent(); 
 566         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 570     if ((y_pos 
!= -1) && (m_yScrollPixelsPerLine
)) 
 572         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 573         if (max 
< 0) max 
= 0; 
 574         if (y_pos 
> max
) y_pos 
= max
; 
 575         if (y_pos 
< 0) y_pos 
= 0; 
 577         int old_y 
= m_yScrollPosition
; 
 578         m_yScrollPosition 
= y_pos
; 
 579         m_vAdjust
->value 
= y_pos
; 
 581         m_targetWindow
->ScrollWindow( 0, (old_y
-m_yScrollPosition
)*m_yScrollPixelsPerLine 
); 
 583         // Just update the scrollbar, don't send any wxWidgets event 
 584         GtkVDisconnectEvent(); 
 585         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 590 // TODO: [VH]Scroll functions should be combined 
 592 void wxScrolledWindow::GtkVScroll( float value
, unsigned int scroll_type 
) 
 594     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 596     if (m_yScrollPixelsPerLine 
== 0) 
 599     int y_pos 
= (int)(value
+0.5); 
 601     if (y_pos 
== m_yScrollPosition
) 
 604     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 606     wxScrollWinEvent 
event( command
, y_pos
, wxVERTICAL 
); 
 607     event
.SetEventObject( this ); 
 608     GetEventHandler()->ProcessEvent( event 
); 
 611 void wxScrolledWindow::GtkHScroll( float value
, unsigned int scroll_type 
) 
 613     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 615     if (m_xScrollPixelsPerLine 
== 0) 
 618     int x_pos 
= (int)(value
+0.5); 
 620     if (x_pos 
== m_xScrollPosition
) 
 623     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 625     wxScrollWinEvent 
event( command
, x_pos
, wxHORIZONTAL 
); 
 626     event
.SetEventObject( this ); 
 627     GetEventHandler()->ProcessEvent( event 
); 
 630 void wxScrolledWindow::EnableScrolling (bool x_scroll
, bool y_scroll
) 
 632     m_xScrollingEnabled 
= x_scroll
; 
 633     m_yScrollingEnabled 
= y_scroll
; 
 636 // Where the current view starts from 
 637 void wxScrolledWindow::GetViewStart (int *x
, int *y
) const 
 640         *x 
= m_xScrollPosition
; 
 642         *y 
= m_yScrollPosition
; 
 645 void wxScrolledWindow::DoCalcScrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 648     GetViewStart (& xs
, & ys
); 
 651         *xx 
= x 
- xs 
* m_xScrollPixelsPerLine
; 
 653         *yy 
= y 
- ys 
* m_yScrollPixelsPerLine
; 
 656 void wxScrolledWindow::DoCalcUnscrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 659     GetViewStart (& xs
, & ys
); 
 662         *xx 
= x 
+ xs 
* m_xScrollPixelsPerLine
; 
 664         *yy 
= y 
+ ys 
* m_yScrollPixelsPerLine
; 
 667 int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent
& event
) 
 669     int pos 
= event
.GetPosition(); 
 670     int orient 
= event
.GetOrientation(); 
 673     if (event
.GetEventType() == wxEVT_SCROLLWIN_TOP
) 
 675             if (orient 
== wxHORIZONTAL
) 
 676                 nScrollInc 
= - m_xScrollPosition
; 
 678                 nScrollInc 
= - m_yScrollPosition
; 
 680     if (event
.GetEventType() == wxEVT_SCROLLWIN_BOTTOM
) 
 682             if (orient 
== wxHORIZONTAL
) 
 683                 nScrollInc 
= GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine 
- m_xScrollPosition
; 
 685                 nScrollInc 
= GetVirtualSize().GetHeight() / m_yScrollPixelsPerLine 
- m_yScrollPosition
; 
 687     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) 
 691     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) 
 695     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEUP
) 
 697             if (orient 
== wxHORIZONTAL
) 
 698                 nScrollInc 
= -GetScrollPageSize(wxHORIZONTAL
); 
 700                 nScrollInc 
= -GetScrollPageSize(wxVERTICAL
); 
 702     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN
) 
 704             if (orient 
== wxHORIZONTAL
) 
 705                 nScrollInc 
= GetScrollPageSize(wxHORIZONTAL
); 
 707                 nScrollInc 
= GetScrollPageSize(wxVERTICAL
); 
 709     if ((event
.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK
) || 
 710         (event
.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE
)) 
 712             if (orient 
== wxHORIZONTAL
) 
 713                 nScrollInc 
= pos 
- m_xScrollPosition
; 
 715                 nScrollInc 
= pos 
- m_yScrollPosition
; 
 718     if (orient 
== wxHORIZONTAL
) 
 720         if (m_xScrollPixelsPerLine 
> 0) 
 722             int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 723             if (max 
< 0) max 
= 0; 
 725             if ( (m_xScrollPosition 
+ nScrollInc
) < 0 ) 
 726                 nScrollInc 
= -m_xScrollPosition
; // As -ve as we can go 
 727             else if ( (m_xScrollPosition 
+ nScrollInc
) > max 
) 
 728                 nScrollInc 
= max 
- m_xScrollPosition
; // As +ve as we can go 
 731             m_targetWindow
->Refresh(); 
 735         if (m_yScrollPixelsPerLine 
> 0) 
 737             int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 738             if (max 
< 0) max 
= 0; 
 740             if ( (m_yScrollPosition 
+ nScrollInc
) < 0 ) 
 741                 nScrollInc 
= -m_yScrollPosition
; // As -ve as we can go 
 742             else if ( (m_yScrollPosition 
+ nScrollInc
) > max 
) 
 743                 nScrollInc 
= max 
- m_yScrollPosition
; // As +ve as we can go 
 746             m_targetWindow
->Refresh(); 
 752 void wxScrolledWindow::SetScrollPos( int orient
, int pos
, bool refresh 
) 
 754     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
 756     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
 758     if (orient 
== wxHORIZONTAL
) 
 760         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 761         if (max 
< 0) max 
= 0; 
 763         if (pos 
> max
) pos 
= 0; 
 764         if (pos 
< 0) pos 
= 0; 
 766         if (pos 
== (int)(m_hAdjust
->value
+0.5)) return; 
 767         m_hAdjust
->value 
= pos
; 
 771         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 772         if (max 
< 0) max 
= 0; 
 774         if (pos 
> max
) pos 
= 0; 
 775         if (pos 
< 0) pos 
= 0; 
 777         if (pos 
== (int)(m_vAdjust
->value
+0.5)) return; 
 778         m_vAdjust
->value 
= pos
; 
 781     if (m_wxwindow
->window
) 
 783         if (orient 
== wxHORIZONTAL
) 
 785             // Just update the scrollbar, don't send any wxWidgets event 
 786             GtkHDisconnectEvent(); 
 787             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 792             // Just update the scrollbar, don't send any wxWidgets event 
 793             GtkVDisconnectEvent(); 
 794             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 800 void wxScrolledWindow::GtkVConnectEvent() 
 802     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
 803           (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 806 void wxScrolledWindow::GtkHConnectEvent() 
 808     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
 809           (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 812 void wxScrolledWindow::GtkHDisconnectEvent() 
 814     gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
 815         (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 818 void wxScrolledWindow::GtkVDisconnectEvent() 
 820     gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
 821         (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 824 bool wxScrolledWindow::Layout() 
 826     if (GetSizer() && m_targetWindow 
== this) 
 828         // If we're the scroll target, take into account the 
 829         // virtual size and scrolled position of the window. 
 832         CalcScrolledPosition(0,0, &x
,&y
); 
 833         GetVirtualSize(&w
, &h
); 
 834         GetSizer()->SetDimension(x
, y
, w
, h
); 
 838         return wxPanel::Layout();  // fall back to default for LayoutConstraints 
 841 // ---------------------------------------------------------------------------- 
 843 // ---------------------------------------------------------------------------- 
 845 // Default OnSize resets scrollbars, if any 
 846 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 848     if( GetAutoLayout() || m_targetWindow
->GetAutoLayout() ) 
 850         if( m_targetWindow 
!= this ) 
 851             m_targetWindow
->FitInside(); 
 855         // FIXME:  Something is really weird here...  This should be 
 856         // called by FitInside above (and apparently is), yet the 
 857         // scrollsub sample will get the scrollbar wrong if resized 
 858         // quickly.  This masks the bug, but is surely not the right 
 868 // This calls OnDraw, having adjusted the origin according to the current 
 870 void wxScrolledWindow::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 878 // kbd handling: notice that we use OnChar() and not OnKeyDown() for 
 879 // compatibility here - if we used OnKeyDown(), the programs which process 
 880 // arrows themselves in their OnChar() would never get the message and like 
 881 // this they always have the priority 
 882 void wxScrolledWindow::OnChar(wxKeyEvent
& event
) 
 884     int stx
, sty
,       // view origin 
 885         szx
, szy
,       // view size (total) 
 886         clix
, cliy
;     // view size (on screen) 
 888     GetViewStart(&stx
, &sty
); 
 889     GetClientSize(&clix
, &cliy
); 
 890     GetVirtualSize(&szx
, &szy
); 
 892     if( m_xScrollPixelsPerLine 
) 
 894         clix 
/= m_xScrollPixelsPerLine
; 
 895         szx 
/= m_xScrollPixelsPerLine
; 
 902     if( m_yScrollPixelsPerLine 
) 
 904         cliy 
/= m_yScrollPixelsPerLine
; 
 905         szy 
/= m_yScrollPixelsPerLine
; 
 913     int xScrollOld 
= GetScrollPos(wxHORIZONTAL
), 
 914         yScrollOld 
= GetScrollPos(wxVERTICAL
); 
 917     switch ( event
.GetKeyCode() ) 
 921             dsty 
= sty 
- (5 * cliy 
/ 6); 
 922             Scroll(-1, (dsty 
== -1) ? 0 : dsty
); 
 927             Scroll(-1, sty 
+ (5 * cliy 
/ 6)); 
 931             Scroll(0, event
.ControlDown() ? 0 : -1); 
 935             Scroll(szx 
- clix
, event
.ControlDown() ? szy 
- cliy 
: -1); 
 960     int xScroll 
= GetScrollPos(wxHORIZONTAL
); 
 961     if ( xScroll 
!= xScrollOld 
) 
 963         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, xScroll
, 
 965         event
.SetEventObject(this); 
 966         GetEventHandler()->ProcessEvent(event
); 
 969     int yScroll 
= GetScrollPos(wxVERTICAL
); 
 970     if ( yScroll 
!= yScrollOld 
) 
 972         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, yScroll
, 
 974         event
.SetEventObject(this); 
 975         GetEventHandler()->ProcessEvent(event
);