1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/scrolwin.cpp 
   3 // Purpose:     wxScrolledWindow implementation 
   4 // Author:      Julian Smart 
   5 // Modified by: Ron Lee 
   8 // Copyright:   (c) Julian Smart 
   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" 
  32 #include "wx/dcclient.h" 
  34 #include "wx/scrolwin.h" 
  38 #include "wx/gtk/private.h" 
  39 #include "wx/gtk/win_gtk.h" 
  41 // ---------------------------------------------------------------------------- 
  43 // ---------------------------------------------------------------------------- 
  45 BEGIN_EVENT_TABLE(wxScrolledWindow
, wxPanel
) 
  46     EVT_SCROLLWIN(wxScrolledWindow::OnScroll
) 
  47     EVT_SIZE(wxScrolledWindow::OnSize
) 
  48     EVT_PAINT(wxScrolledWindow::OnPaint
) 
  49     EVT_CHAR(wxScrolledWindow::OnChar
) 
  52 IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow
, wxPanel
) 
  54 // ============================================================================ 
  56 // ============================================================================ 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  62 extern bool       g_blockEventsOnDrag
; 
  63 extern bool       g_blockEventsOnScroll
; 
  65 //----------------------------------------------------------------------------- 
  67 //----------------------------------------------------------------------------- 
  69 extern void wxapp_install_idle_handler(); 
  72 //----------------------------------------------------------------------------- 
  73 // "value_changed" from m_vAdjust 
  74 //----------------------------------------------------------------------------- 
  76 static void gtk_scrolled_window_vscroll_callback( GtkAdjustment 
*adjust
, 
  78                                                   wxScrolledWindow 
*win 
) 
  81         wxapp_install_idle_handler(); 
  83     if (g_blockEventsOnDrag
) return; 
  85     if (!win
->m_hasVMT
) return; 
  87     win
->GtkVScroll( adjust
->value
, 
  88             GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win
->m_widget
)->vscrollbar
) ); 
  91 //----------------------------------------------------------------------------- 
  92 // "value_changed" from m_hAdjust 
  93 //----------------------------------------------------------------------------- 
  95 static void gtk_scrolled_window_hscroll_callback( GtkAdjustment 
*adjust
, 
  97                                                   wxScrolledWindow 
*win 
) 
 100         wxapp_install_idle_handler(); 
 102     if (g_blockEventsOnDrag
) return; 
 103     if (!win
->m_hasVMT
) return; 
 105     win
->GtkHScroll( adjust
->value
, 
 106             GET_SCROLL_TYPE(GTK_SCROLLED_WINDOW(win
->m_widget
)->hscrollbar
) ); 
 109 //----------------------------------------------------------------------------- 
 110 // "button_press_event" from scrollbar 
 111 //----------------------------------------------------------------------------- 
 113 static gint 
gtk_scrollbar_button_press_callback( GtkRange 
*widget
, 
 114                                                  GdkEventButton 
*gdk_event
, 
 118         wxapp_install_idle_handler(); 
 120     g_blockEventsOnScroll 
= TRUE
; 
 122     // FIXME: there is no slider field any more, what was meant here? 
 124     win
->m_isScrolling 
= (gdk_event
->window 
== widget
->slider
); 
 130 //----------------------------------------------------------------------------- 
 131 // "button_release_event" from scrollbar 
 132 //----------------------------------------------------------------------------- 
 134 static gint 
gtk_scrollbar_button_release_callback( GtkRange 
*widget
, 
 135                                                    GdkEventButton 
*WXUNUSED(gdk_event
), 
 138 //  don't test here as we can release the mouse while being over 
 139 //  a different window than the slider 
 141 //    if (gdk_event->window != widget->slider) return FALSE; 
 143     g_blockEventsOnScroll 
= FALSE
; 
 145     if (win
->m_isScrolling
) 
 147         wxEventType command 
= wxEVT_SCROLLWIN_THUMBRELEASE
; 
 151         GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(win
->m_widget
); 
 152         if (widget 
== GTK_RANGE(scrolledWindow
->hscrollbar
)) 
 154             value 
= (int)(win
->m_hAdjust
->value
+0.5); 
 157         if (widget 
== GTK_RANGE(scrolledWindow
->vscrollbar
)) 
 159             value 
= (int)(win
->m_vAdjust
->value
+0.5); 
 163         wxScrollWinEvent 
event( command
, value
, dir 
); 
 164         event
.SetEventObject( win 
); 
 165         win
->GetEventHandler()->ProcessEvent( event 
); 
 168     win
->m_isScrolling 
= FALSE
; 
 173 //----------------------------------------------------------------------------- 
 174 // InsertChild for wxScrolledWindow 
 175 //----------------------------------------------------------------------------- 
 177 static void wxInsertChildInScrolledWindow( wxWindow
* parent
, wxWindow
* child 
) 
 179     // The window might have been scrolled already, do we 
 180     // have to adapt the position. 
 181     GtkPizza 
*pizza 
= GTK_PIZZA(parent
->m_wxwindow
); 
 182     child
->m_x 
+= pizza
->xoffset
; 
 183     child
->m_y 
+= pizza
->yoffset
; 
 185     gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
), 
 186                      GTK_WIDGET(child
->m_widget
), 
 193 // ---------------------------------------------------------------------------- 
 194 // wxScrolledWindow creation 
 195 // ---------------------------------------------------------------------------- 
 197 void wxScrolledWindow::Init() 
 199     m_xScrollPixelsPerLine 
= 0; 
 200     m_yScrollPixelsPerLine 
= 0; 
 201     m_xScrollingEnabled 
= TRUE
; 
 202     m_yScrollingEnabled 
= TRUE
; 
 203     m_xScrollPosition 
= 0; 
 204     m_yScrollPosition 
= 0; 
 205     m_xScrollLinesPerPage 
= 0; 
 206     m_yScrollLinesPerPage 
= 0; 
 207     m_targetWindow 
= (wxWindow
*) NULL
; 
 210     m_hasScrolling 
= TRUE
; 
 213 bool wxScrolledWindow::Create(wxWindow 
*parent
, 
 218                               const wxString
& name
) 
 222     if (!PreCreation( parent
, pos
, size 
) || 
 223         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 225         wxFAIL_MSG( wxT("wxWindow creation failed") ); 
 229     m_insertCallback 
= wxInsertChildInScrolledWindow
; 
 231     m_targetWindow 
= this; 
 233     m_widget 
= gtk_scrolled_window_new( (GtkAdjustment 
*) NULL
, (GtkAdjustment 
*) NULL 
); 
 234     GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS 
); 
 236     GtkScrolledWindow 
*scrolledWindow 
= GTK_SCROLLED_WINDOW(m_widget
); 
 238     GtkScrolledWindowClass 
*scroll_class 
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) ); 
 239     scroll_class
->scrollbar_spacing 
= 0; 
 241     gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC 
); 
 243     m_hAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) ); 
 244     m_vAdjust 
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) ); 
 246     m_wxwindow 
= gtk_pizza_new(); 
 248     gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow 
); 
 250     GtkPizza 
*pizza 
= GTK_PIZZA(m_wxwindow
); 
 252     if (HasFlag(wxRAISED_BORDER
)) 
 254         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT 
); 
 256     else if (HasFlag(wxSUNKEN_BORDER
)) 
 258         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN 
); 
 260     else if (HasFlag(wxSIMPLE_BORDER
)) 
 262         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN 
); 
 266         gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE 
); 
 269     GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS 
); 
 270     m_acceptsFocus 
= TRUE
; 
 272     // I _really_ don't want scrollbars in the beginning 
 273     m_vAdjust
->lower 
= 0.0; 
 274     m_vAdjust
->upper 
= 1.0; 
 275     m_vAdjust
->value 
= 0.0; 
 276     m_vAdjust
->step_increment 
= 1.0; 
 277     m_vAdjust
->page_increment 
= 2.0; 
 278     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 279     m_hAdjust
->lower 
= 0.0; 
 280     m_hAdjust
->upper 
= 1.0; 
 281     m_hAdjust
->value 
= 0.0; 
 282     m_hAdjust
->step_increment 
= 1.0; 
 283     m_hAdjust
->page_increment 
= 2.0; 
 284     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 286     // Handlers for new scrollbar values 
 290     // these handlers block mouse events to any window during scrolling such as 
 291     // motion events and prevent GTK and wxWindows from fighting over where the 
 294     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event", 
 295           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 297     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event", 
 298           (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this ); 
 300     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event", 
 301           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 303     gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event", 
 304           (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this ); 
 306     gtk_widget_show( m_wxwindow 
); 
 309         m_parent
->DoAddChild( this ); 
 311     m_focusWidget 
= m_wxwindow
; 
 320 // ---------------------------------------------------------------------------- 
 321 // setting scrolling parameters 
 322 // ---------------------------------------------------------------------------- 
 324 void wxScrolledWindow::DoSetVirtualSize( int x
, int y 
) 
 326     wxPanel::DoSetVirtualSize( x
, y 
); 
 329 #if wxUSE_CONSTRAINTS 
 336  * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) 
 337  * noUnitsX/noUnitsY:        : no. units per scrollbar 
 339 void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX
, int pixelsPerUnitY
, 
 340                                       int noUnitsX
, int noUnitsY
, 
 341                                       int xPos
, int yPos
, bool noRefresh 
) 
 344     GetViewStart (& xs
, & ys
); 
 346     int old_x 
= m_xScrollPixelsPerLine 
* xs
; 
 347     int old_y 
= m_yScrollPixelsPerLine 
* ys
; 
 349     m_xScrollPixelsPerLine 
= pixelsPerUnitX
; 
 350     m_yScrollPixelsPerLine 
= pixelsPerUnitY
; 
 352     m_hAdjust
->value 
= m_xScrollPosition 
= xPos
; 
 353     m_vAdjust
->value 
= m_yScrollPosition 
= yPos
; 
 355     // Setting hints here should arguably be deprecated, but without it 
 356     // a sizer might override this manual scrollbar setting in old code. 
 357     m_targetWindow
->SetVirtualSizeHints( noUnitsX 
* pixelsPerUnitX
, noUnitsY 
* pixelsPerUnitY 
); 
 359     m_targetWindow
->SetVirtualSize( noUnitsX 
* pixelsPerUnitX
, noUnitsY 
* pixelsPerUnitY 
); 
 363         int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 364         int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 366         m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 370 void wxScrolledWindow::AdjustScrollbars() 
 375     m_targetWindow
->GetClientSize( &w
, &h 
); 
 376     m_targetWindow
->GetVirtualSize( &vw
, &vh 
); 
 378     if (m_xScrollPixelsPerLine 
== 0) 
 380         m_hAdjust
->upper 
= 1.0; 
 381         m_hAdjust
->page_size 
= 1.0; 
 385         m_hAdjust
->upper 
= vw 
/ m_xScrollPixelsPerLine
; 
 386         m_hAdjust
->page_size 
= (w 
/ m_xScrollPixelsPerLine
); 
 388         // If the scrollbar hits the right side, move the window 
 389         // right to keep it from over extending. 
 391         if ((m_hAdjust
->value 
!= 0.0) && (m_hAdjust
->value 
+ m_hAdjust
->page_size 
> m_hAdjust
->upper
)) 
 393             m_hAdjust
->value 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
 394             if (m_hAdjust
->value 
< 0.0) 
 395                 m_hAdjust
->value 
= 0.0; 
 397             if (GetChildren().GetCount() == 0) 
 398                 m_xScrollPosition 
= (int)m_hAdjust
->value
; // This is enough without child windows 
 400                 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); // Actually scroll window 
 404     if (m_yScrollPixelsPerLine 
== 0) 
 406         m_vAdjust
->upper 
= 1.0; 
 407         m_vAdjust
->page_size 
= 1.0; 
 411         m_vAdjust
->upper 
= vh 
/ m_yScrollPixelsPerLine
; 
 412         m_vAdjust
->page_size 
= (h 
/ m_yScrollPixelsPerLine
); 
 414         if ((m_vAdjust
->value 
!= 0.0) && (m_vAdjust
->value 
+ m_vAdjust
->page_size 
> m_vAdjust
->upper
)) 
 416             m_vAdjust
->value 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
 417             if (m_vAdjust
->value 
< 0.0) 
 418                 m_vAdjust
->value 
= 0.0; 
 420             if (GetChildren().GetCount() == 0) 
 421                 m_yScrollPosition 
= (int)m_vAdjust
->value
;   
 423                 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 427     m_xScrollLinesPerPage 
= (int)(m_hAdjust
->page_size 
+ 0.5); 
 428     m_yScrollLinesPerPage 
= (int)(m_vAdjust
->page_size 
+ 0.5); 
 430     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 431     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 435 // ---------------------------------------------------------------------------- 
 436 // target window handling 
 437 // ---------------------------------------------------------------------------- 
 439 void wxScrolledWindow::SetTargetWindow( wxWindow 
*target
, bool WXUNUSED(pushEventHandler
) ) 
 441     wxASSERT_MSG( target
, wxT("target window must not be NULL") ); 
 442     m_targetWindow 
= target
; 
 445 wxWindow 
*wxScrolledWindow::GetTargetWindow() const 
 447     return m_targetWindow
; 
 450 // Override this function if you don't want to have wxScrolledWindow 
 451 // automatically change the origin according to the scroll position. 
 452 void wxScrolledWindow::PrepareDC(wxDC
& dc
) 
 454     dc
.SetDeviceOrigin( -m_xScrollPosition 
* m_xScrollPixelsPerLine
, 
 455                         -m_yScrollPosition 
* m_yScrollPixelsPerLine 
); 
 458 void wxScrolledWindow::SetScrollRate( int xstep
, int ystep 
) 
 460     int old_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 461     int old_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 463     m_xScrollPixelsPerLine 
= xstep
; 
 464     m_yScrollPixelsPerLine 
= ystep
; 
 466     int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 467     int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 469     m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 474 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const 
 477         *x_unit 
= m_xScrollPixelsPerLine
; 
 479         *y_unit 
= m_yScrollPixelsPerLine
; 
 482 int wxScrolledWindow::GetScrollPageSize(int orient
) const 
 484     if ( orient 
== wxHORIZONTAL 
) 
 485         return m_xScrollLinesPerPage
; 
 487         return m_yScrollLinesPerPage
; 
 490 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
) 
 492     if ( orient 
== wxHORIZONTAL 
) 
 493         m_xScrollLinesPerPage 
= pageSize
; 
 495         m_yScrollLinesPerPage 
= pageSize
; 
 498 void wxScrolledWindow::OnScroll(wxScrollWinEvent
& event
) 
 500     int orient 
= event
.GetOrientation(); 
 502     int nScrollInc 
= CalcScrollInc(event
); 
 503     if (nScrollInc 
== 0) return; 
 505     if (orient 
== wxHORIZONTAL
) 
 507         int newPos 
= m_xScrollPosition 
+ nScrollInc
; 
 508         SetScrollPos(wxHORIZONTAL
, newPos
, TRUE 
); 
 512         int newPos 
= m_yScrollPosition 
+ nScrollInc
; 
 513         SetScrollPos(wxVERTICAL
, newPos
, TRUE 
); 
 516     if (orient 
== wxHORIZONTAL
) 
 518         m_xScrollPosition 
+= nScrollInc
; 
 522         m_yScrollPosition 
+= nScrollInc
; 
 525     if (orient 
== wxHORIZONTAL
) 
 527        if (m_xScrollingEnabled
) 
 528             m_targetWindow
->ScrollWindow(-m_xScrollPixelsPerLine 
* nScrollInc
, 0, (const wxRect 
*) NULL
); 
 530             m_targetWindow
->Refresh(); 
 534         if (m_yScrollingEnabled
) 
 535             m_targetWindow
->ScrollWindow(0, -m_yScrollPixelsPerLine 
* nScrollInc
, (const wxRect 
*) NULL
); 
 537             m_targetWindow
->Refresh(); 
 541 void wxScrolledWindow::Scroll( int x_pos
, int y_pos 
) 
 543     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 545     if (((x_pos 
== -1) || (x_pos 
== m_xScrollPosition
)) && 
 546         ((y_pos 
== -1) || (y_pos 
== m_yScrollPosition
))) return; 
 548     if ((x_pos 
!= -1) && (m_xScrollPixelsPerLine
)) 
 550         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 551         if (max 
< 0) max 
= 0; 
 552         if (x_pos 
> max
) x_pos 
= max
; 
 553         if (x_pos 
< 0) x_pos 
= 0; 
 555         int old_x 
= m_xScrollPosition
; 
 556         m_xScrollPosition 
= x_pos
; 
 557         m_hAdjust
->value 
= x_pos
; 
 559         m_targetWindow
->ScrollWindow( (old_x
-m_xScrollPosition
)*m_xScrollPixelsPerLine
, 0 ); 
 561         // Just update the scrollbar, don't send any wxWindows event 
 562         GtkHDisconnectEvent(); 
 563         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 567     if ((y_pos 
!= -1) && (m_yScrollPixelsPerLine
)) 
 569         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 570         if (max 
< 0) max 
= 0; 
 571         if (y_pos 
> max
) y_pos 
= max
; 
 572         if (y_pos 
< 0) y_pos 
= 0; 
 574         int old_y 
= m_yScrollPosition
; 
 575         m_yScrollPosition 
= y_pos
; 
 576         m_vAdjust
->value 
= y_pos
; 
 578         m_targetWindow
->ScrollWindow( 0, (old_y
-m_yScrollPosition
)*m_yScrollPixelsPerLine 
); 
 580         // Just update the scrollbar, don't send any wxWindows event 
 581         GtkVDisconnectEvent(); 
 582         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 587 // TODO: [VH]Scroll functions should be combined 
 589 void wxScrolledWindow::GtkVScroll( float value
, unsigned int scroll_type 
) 
 591     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 593     if (m_yScrollPixelsPerLine 
== 0) 
 596     int y_pos 
= (int)(value
+0.5); 
 598     if (y_pos 
== m_yScrollPosition
) 
 601     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 603     wxScrollWinEvent 
event( command
, y_pos
, wxVERTICAL 
); 
 604     event
.SetEventObject( this ); 
 605     GetEventHandler()->ProcessEvent( event 
); 
 608 void wxScrolledWindow::GtkHScroll( float value
, unsigned int scroll_type 
) 
 610     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 612     if (m_xScrollPixelsPerLine 
== 0) 
 615     int x_pos 
= (int)(value
+0.5); 
 617     if (x_pos 
== m_xScrollPosition
) 
 620     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 622     wxScrollWinEvent 
event( command
, x_pos
, wxHORIZONTAL 
); 
 623     event
.SetEventObject( this ); 
 624     GetEventHandler()->ProcessEvent( event 
); 
 627 void wxScrolledWindow::EnableScrolling (bool x_scroll
, bool y_scroll
) 
 629     m_xScrollingEnabled 
= x_scroll
; 
 630     m_yScrollingEnabled 
= y_scroll
; 
 633 // Where the current view starts from 
 634 void wxScrolledWindow::GetViewStart (int *x
, int *y
) const 
 637         *x 
= m_xScrollPosition
; 
 639         *y 
= m_yScrollPosition
; 
 642 void wxScrolledWindow::DoCalcScrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 645     GetViewStart (& xs
, & ys
); 
 648         *xx 
= x 
- xs 
* m_xScrollPixelsPerLine
; 
 650         *yy 
= y 
- ys 
* m_yScrollPixelsPerLine
; 
 653 void wxScrolledWindow::DoCalcUnscrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 656     GetViewStart (& xs
, & ys
); 
 659         *xx 
= x 
+ xs 
* m_xScrollPixelsPerLine
; 
 661         *yy 
= y 
+ ys 
* m_yScrollPixelsPerLine
; 
 664 int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent
& event
) 
 666     int pos 
= event
.GetPosition(); 
 667     int orient 
= event
.GetOrientation(); 
 670     if (event
.GetEventType() == wxEVT_SCROLLWIN_TOP
) 
 672             if (orient 
== wxHORIZONTAL
) 
 673                 nScrollInc 
= - m_xScrollPosition
; 
 675                 nScrollInc 
= - m_yScrollPosition
; 
 677     if (event
.GetEventType() == wxEVT_SCROLLWIN_BOTTOM
) 
 679             if (orient 
== wxHORIZONTAL
) 
 680                 nScrollInc 
= GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine 
- m_xScrollPosition
; 
 682                 nScrollInc 
= GetVirtualSize().GetHeight() / m_yScrollPixelsPerLine 
- m_yScrollPosition
; 
 684     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) 
 688     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) 
 692     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEUP
) 
 694             if (orient 
== wxHORIZONTAL
) 
 695                 nScrollInc 
= -GetScrollPageSize(wxHORIZONTAL
); 
 697                 nScrollInc 
= -GetScrollPageSize(wxVERTICAL
); 
 699     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN
) 
 701             if (orient 
== wxHORIZONTAL
) 
 702                 nScrollInc 
= GetScrollPageSize(wxHORIZONTAL
); 
 704                 nScrollInc 
= GetScrollPageSize(wxVERTICAL
); 
 706     if ((event
.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK
) || 
 707         (event
.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE
)) 
 709             if (orient 
== wxHORIZONTAL
) 
 710                 nScrollInc 
= pos 
- m_xScrollPosition
; 
 712                 nScrollInc 
= pos 
- m_yScrollPosition
; 
 715     if (orient 
== wxHORIZONTAL
) 
 717         if (m_xScrollPixelsPerLine 
> 0) 
 719             int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 720             if (max 
< 0) max 
= 0; 
 722             if ( (m_xScrollPosition 
+ nScrollInc
) < 0 ) 
 723                 nScrollInc 
= -m_xScrollPosition
; // As -ve as we can go 
 724             else if ( (m_xScrollPosition 
+ nScrollInc
) > max 
) 
 725                 nScrollInc 
= max 
- m_xScrollPosition
; // As +ve as we can go 
 728             m_targetWindow
->Refresh(); 
 732         if (m_yScrollPixelsPerLine 
> 0) 
 734             int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 735             if (max 
< 0) max 
= 0; 
 737             if ( (m_yScrollPosition 
+ nScrollInc
) < 0 ) 
 738                 nScrollInc 
= -m_yScrollPosition
; // As -ve as we can go 
 739             else if ( (m_yScrollPosition 
+ nScrollInc
) > max 
) 
 740                 nScrollInc 
= max 
- m_yScrollPosition
; // As +ve as we can go 
 743             m_targetWindow
->Refresh(); 
 749 void wxScrolledWindow::SetScrollPos( int orient
, int pos
, bool refresh 
) 
 751     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
 753     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
 755     if (orient 
== wxHORIZONTAL
) 
 757         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 758         if (max 
< 0) max 
= 0; 
 760         if (pos 
> max
) pos 
= 0; 
 761         if (pos 
< 0) pos 
= 0; 
 763         if (pos 
== (int)(m_hAdjust
->value
+0.5)) return; 
 764         m_hAdjust
->value 
= pos
; 
 768         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 769         if (max 
< 0) max 
= 0; 
 771         if (pos 
> max
) pos 
= 0; 
 772         if (pos 
< 0) pos 
= 0; 
 774         if (pos 
== (int)(m_vAdjust
->value
+0.5)) return; 
 775         m_vAdjust
->value 
= pos
; 
 778     if (m_wxwindow
->window
) 
 780         if (orient 
== wxHORIZONTAL
) 
 782             // Just update the scrollbar, don't send any wxWindows event 
 783             GtkHDisconnectEvent(); 
 784             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 789             // Just update the scrollbar, don't send any wxWindows event 
 790             GtkVDisconnectEvent(); 
 791             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 797 void wxScrolledWindow::GtkVConnectEvent() 
 799     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
 800           (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 803 void wxScrolledWindow::GtkHConnectEvent() 
 805     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
 806           (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 809 void wxScrolledWindow::GtkHDisconnectEvent() 
 811     gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
 812         (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 815 void wxScrolledWindow::GtkVDisconnectEvent() 
 817     gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
 818         (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 821 bool wxScrolledWindow::Layout() 
 823     if (GetSizer() && m_targetWindow 
== this) 
 825         // If we're the scroll target, take into account the 
 826         // virtual size and scrolled position of the window. 
 829         CalcScrolledPosition(0,0, &x
,&y
); 
 830         GetVirtualSize(&w
, &h
); 
 831         GetSizer()->SetDimension(x
, y
, w
, h
); 
 835         return wxPanel::Layout();  // fall back to default for LayoutConstraints 
 838 // ---------------------------------------------------------------------------- 
 840 // ---------------------------------------------------------------------------- 
 842 // Default OnSize resets scrollbars, if any 
 843 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 845     if( GetAutoLayout() || m_targetWindow
->GetAutoLayout() ) 
 847         if( m_targetWindow 
!= this ) 
 848             m_targetWindow
->FitInside(); 
 852         // FIXME:  Something is really weird here...  This should be 
 853         // called by FitInside above (and apparently is), yet the 
 854         // scrollsub sample will get the scrollbar wrong if resized 
 855         // quickly.  This masks the bug, but is surely not the right 
 865 // This calls OnDraw, having adjusted the origin according to the current 
 867 void wxScrolledWindow::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 875 // kbd handling: notice that we use OnChar() and not OnKeyDown() for 
 876 // compatibility here - if we used OnKeyDown(), the programs which process 
 877 // arrows themselves in their OnChar() would never get the message and like 
 878 // this they always have the priority 
 879 void wxScrolledWindow::OnChar(wxKeyEvent
& event
) 
 881     int stx
, sty
,       // view origin 
 882         szx
, szy
,       // view size (total) 
 883         clix
, cliy
;     // view size (on screen) 
 885     GetViewStart(&stx
, &sty
); 
 886     GetClientSize(&clix
, &cliy
); 
 887     GetVirtualSize(&szx
, &szy
); 
 889     if( m_xScrollPixelsPerLine 
) 
 891         clix 
/= m_xScrollPixelsPerLine
; 
 892         szx 
/= m_xScrollPixelsPerLine
; 
 899     if( m_yScrollPixelsPerLine 
) 
 901         cliy 
/= m_yScrollPixelsPerLine
; 
 902         szy 
/= m_yScrollPixelsPerLine
; 
 910     int xScrollOld 
= GetScrollPos(wxHORIZONTAL
), 
 911         yScrollOld 
= GetScrollPos(wxVERTICAL
); 
 914     switch ( event
.GetKeyCode() ) 
 918             dsty 
= sty 
- (5 * cliy 
/ 6); 
 919             Scroll(-1, (dsty 
== -1) ? 0 : dsty
); 
 924             Scroll(-1, sty 
+ (5 * cliy 
/ 6)); 
 928             Scroll(0, event
.ControlDown() ? 0 : -1); 
 932             Scroll(szx 
- clix
, event
.ControlDown() ? szy 
- cliy 
: -1); 
 957     int xScroll 
= GetScrollPos(wxHORIZONTAL
); 
 958     if ( xScroll 
!= xScrollOld 
) 
 960         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, xScroll
, 
 962         event
.SetEventObject(this); 
 963         GetEventHandler()->ProcessEvent(event
); 
 966     int yScroll 
= GetScrollPos(wxVERTICAL
); 
 967     if ( yScroll 
!= yScrollOld 
) 
 969         wxScrollWinEvent 
event(wxEVT_SCROLLWIN_THUMBTRACK
, yScroll
, 
 971         event
.SetEventObject(this); 
 972         GetEventHandler()->ProcessEvent(event
);