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 
); 
 333  * pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line) 
 334  * noUnitsX/noUnitsY:        : no. units per scrollbar 
 336 void wxScrolledWindow::SetScrollbars( int pixelsPerUnitX
, int pixelsPerUnitY
, 
 337                                       int noUnitsX
, int noUnitsY
, 
 338                                       int xPos
, int yPos
, bool noRefresh 
) 
 341     GetViewStart (& xs
, & ys
); 
 343     int old_x 
= m_xScrollPixelsPerLine 
* xs
; 
 344     int old_y 
= m_yScrollPixelsPerLine 
* ys
; 
 346     m_xScrollPixelsPerLine 
= pixelsPerUnitX
; 
 347     m_yScrollPixelsPerLine 
= pixelsPerUnitY
; 
 349     m_hAdjust
->value 
= m_xScrollPosition 
= xPos
; 
 350     m_vAdjust
->value 
= m_yScrollPosition 
= yPos
; 
 352     // Setting hints here should arguably be deprecated, but without it 
 353     // a sizer might override this manual scrollbar setting in old code. 
 354     // m_targetWindow->SetVirtualSizeHints( noUnitsX * pixelsPerUnitX, noUnitsY * pixelsPerUnitY ); 
 356     m_targetWindow
->SetVirtualSize( noUnitsX 
* pixelsPerUnitX
, noUnitsY 
* pixelsPerUnitY 
); 
 360         int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 361         int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 363         m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 367 void wxScrolledWindow::AdjustScrollbars() 
 372     m_targetWindow
->GetClientSize( &w
, &h 
); 
 373     m_targetWindow
->GetVirtualSize( &vw
, &vh 
); 
 375     if (m_xScrollPixelsPerLine 
== 0) 
 377         m_hAdjust
->upper 
= 1.0; 
 378         m_hAdjust
->page_increment 
= 1.0; 
 379         m_hAdjust
->page_size 
= 1.0; 
 383         m_hAdjust
->upper 
= (vw
+m_xScrollPixelsPerLine
-1) / m_xScrollPixelsPerLine
; 
 384         m_hAdjust
->page_size 
= w 
/ m_xScrollPixelsPerLine
; 
 385         m_hAdjust
->page_increment 
= w 
/ m_xScrollPixelsPerLine
; 
 387         // Special case. When client and virtual size are very close but 
 388         // the client is big enough, kill scrollbar. 
 390         if ((m_hAdjust
->page_size 
< m_hAdjust
->upper
) && (w 
>= vw
))  
 391             m_hAdjust
->page_size 
+= 1.0; 
 393         // If the scrollbar hits the right side, move the window 
 394         // right to keep it from over extending. 
 396         if ((m_hAdjust
->value 
!= 0.0) && (m_hAdjust
->value 
+ m_hAdjust
->page_size 
> m_hAdjust
->upper
)) 
 398             m_hAdjust
->value 
= m_hAdjust
->upper 
- m_hAdjust
->page_size
; 
 399             if (m_hAdjust
->value 
< 0.0) 
 400                 m_hAdjust
->value 
= 0.0; 
 402             if (GetChildren().GetCount() == 0) 
 403                 m_xScrollPosition 
= (int)m_hAdjust
->value
; // This is enough without child windows 
 405                 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); // Actually scroll window 
 409     if (m_yScrollPixelsPerLine 
== 0) 
 411         m_vAdjust
->upper 
= 1.0; 
 412         m_vAdjust
->page_increment 
= 1.0; 
 413         m_vAdjust
->page_size 
= 1.0; 
 417         m_vAdjust
->upper 
= (vh
+m_yScrollPixelsPerLine
-1) / m_yScrollPixelsPerLine
; 
 418         m_vAdjust
->page_size 
= h 
/ m_yScrollPixelsPerLine
; 
 419         m_vAdjust
->page_increment 
= h 
/ m_yScrollPixelsPerLine
; 
 421         if ((m_vAdjust
->page_size 
< m_vAdjust
->upper
) && (h 
>= vh
))  
 422             m_vAdjust
->page_size 
+= 1.0; 
 424         if ((m_vAdjust
->value 
!= 0.0) && (m_vAdjust
->value 
+ m_vAdjust
->page_size 
> m_vAdjust
->upper
)) 
 426             m_vAdjust
->value 
= m_vAdjust
->upper 
- m_vAdjust
->page_size
; 
 427             if (m_vAdjust
->value 
< 0.0) 
 428                 m_vAdjust
->value 
= 0.0; 
 430             if (GetChildren().GetCount() == 0) 
 431                 m_yScrollPosition 
= (int)m_vAdjust
->value
;   
 433                 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 437     m_xScrollLinesPerPage 
= (int)(m_hAdjust
->page_increment 
+ 0.5); 
 438     m_yScrollLinesPerPage 
= (int)(m_vAdjust
->page_increment 
+ 0.5); 
 440     gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" ); 
 441     gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" ); 
 445 // ---------------------------------------------------------------------------- 
 446 // target window handling 
 447 // ---------------------------------------------------------------------------- 
 449 void wxScrolledWindow::SetTargetWindow( wxWindow 
*target
, bool WXUNUSED(pushEventHandler
) ) 
 451     wxASSERT_MSG( target
, wxT("target window must not be NULL") ); 
 452     m_targetWindow 
= target
; 
 455 wxWindow 
*wxScrolledWindow::GetTargetWindow() const 
 457     return m_targetWindow
; 
 460 // Override this function if you don't want to have wxScrolledWindow 
 461 // automatically change the origin according to the scroll position. 
 462 void wxScrolledWindow::DoPrepareDC(wxDC
& dc
) 
 464     dc
.SetDeviceOrigin( -m_xScrollPosition 
* m_xScrollPixelsPerLine
, 
 465                         -m_yScrollPosition 
* m_yScrollPixelsPerLine 
); 
 468 void wxScrolledWindow::SetScrollRate( int xstep
, int ystep 
) 
 470     int old_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 471     int old_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 473     m_xScrollPixelsPerLine 
= xstep
; 
 474     m_yScrollPixelsPerLine 
= ystep
; 
 476     int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
 477     int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
 479     m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
 484 void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit
, int *y_unit
) const 
 487         *x_unit 
= m_xScrollPixelsPerLine
; 
 489         *y_unit 
= m_yScrollPixelsPerLine
; 
 492 int wxScrolledWindow::GetScrollPageSize(int orient
) const 
 494     if ( orient 
== wxHORIZONTAL 
) 
 495         return m_xScrollLinesPerPage
; 
 497         return m_yScrollLinesPerPage
; 
 500 void wxScrolledWindow::SetScrollPageSize(int orient
, int pageSize
) 
 502     if ( orient 
== wxHORIZONTAL 
) 
 503         m_xScrollLinesPerPage 
= pageSize
; 
 505         m_yScrollLinesPerPage 
= pageSize
; 
 508 void wxScrolledWindow::OnScroll(wxScrollWinEvent
& event
) 
 510     int orient 
= event
.GetOrientation(); 
 512     int nScrollInc 
= CalcScrollInc(event
); 
 513     if (nScrollInc 
== 0) return; 
 515     if (orient 
== wxHORIZONTAL
) 
 517         int newPos 
= m_xScrollPosition 
+ nScrollInc
; 
 518         SetScrollPos(wxHORIZONTAL
, newPos
, TRUE 
); 
 522         int newPos 
= m_yScrollPosition 
+ nScrollInc
; 
 523         SetScrollPos(wxVERTICAL
, newPos
, TRUE 
); 
 526     if (orient 
== wxHORIZONTAL
) 
 528         m_xScrollPosition 
+= nScrollInc
; 
 532         m_yScrollPosition 
+= nScrollInc
; 
 535     if (orient 
== wxHORIZONTAL
) 
 537        if (m_xScrollingEnabled
) 
 538             m_targetWindow
->ScrollWindow(-m_xScrollPixelsPerLine 
* nScrollInc
, 0, (const wxRect 
*) NULL
); 
 540             m_targetWindow
->Refresh(); 
 544         if (m_yScrollingEnabled
) 
 545             m_targetWindow
->ScrollWindow(0, -m_yScrollPixelsPerLine 
* nScrollInc
, (const wxRect 
*) NULL
); 
 547             m_targetWindow
->Refresh(); 
 551 void wxScrolledWindow::Scroll( int x_pos
, int y_pos 
) 
 553     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 555     if (((x_pos 
== -1) || (x_pos 
== m_xScrollPosition
)) && 
 556         ((y_pos 
== -1) || (y_pos 
== m_yScrollPosition
))) return; 
 558     if ((x_pos 
!= -1) && (m_xScrollPixelsPerLine
)) 
 560         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 561         if (max 
< 0) max 
= 0; 
 562         if (x_pos 
> max
) x_pos 
= max
; 
 563         if (x_pos 
< 0) x_pos 
= 0; 
 565         int old_x 
= m_xScrollPosition
; 
 566         m_xScrollPosition 
= x_pos
; 
 567         m_hAdjust
->value 
= x_pos
; 
 569         m_targetWindow
->ScrollWindow( (old_x
-m_xScrollPosition
)*m_xScrollPixelsPerLine
, 0 ); 
 571         // Just update the scrollbar, don't send any wxWidgets event 
 572         GtkHDisconnectEvent(); 
 573         gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 577     if ((y_pos 
!= -1) && (m_yScrollPixelsPerLine
)) 
 579         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 580         if (max 
< 0) max 
= 0; 
 581         if (y_pos 
> max
) y_pos 
= max
; 
 582         if (y_pos 
< 0) y_pos 
= 0; 
 584         int old_y 
= m_yScrollPosition
; 
 585         m_yScrollPosition 
= y_pos
; 
 586         m_vAdjust
->value 
= y_pos
; 
 588         m_targetWindow
->ScrollWindow( 0, (old_y
-m_yScrollPosition
)*m_yScrollPixelsPerLine 
); 
 590         // Just update the scrollbar, don't send any wxWidgets event 
 591         GtkVDisconnectEvent(); 
 592         gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 597 // TODO: [VH]Scroll functions should be combined 
 599 void wxScrolledWindow::GtkVScroll( float value
, unsigned int scroll_type 
) 
 601     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 603     if (m_yScrollPixelsPerLine 
== 0) 
 606     int y_pos 
= (int)(value
+0.5); 
 608     if (y_pos 
== m_yScrollPosition
) 
 611     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 613     wxScrollWinEvent 
event( command
, y_pos
, wxVERTICAL 
); 
 614     event
.SetEventObject( this ); 
 615     GetEventHandler()->ProcessEvent( event 
); 
 618 void wxScrolledWindow::GtkHScroll( float value
, unsigned int scroll_type 
) 
 620     wxASSERT_MSG( m_targetWindow 
!= 0, _T("No target window") ); 
 622     if (m_xScrollPixelsPerLine 
== 0) 
 625     int x_pos 
= (int)(value
+0.5); 
 627     if (x_pos 
== m_xScrollPosition
) 
 630     wxEventType command 
= GtkScrollWinTypeToWx(scroll_type
); 
 632     wxScrollWinEvent 
event( command
, x_pos
, wxHORIZONTAL 
); 
 633     event
.SetEventObject( this ); 
 634     GetEventHandler()->ProcessEvent( event 
); 
 637 void wxScrolledWindow::EnableScrolling (bool x_scroll
, bool y_scroll
) 
 639     m_xScrollingEnabled 
= x_scroll
; 
 640     m_yScrollingEnabled 
= y_scroll
; 
 643 // Where the current view starts from 
 644 void wxScrolledWindow::GetViewStart (int *x
, int *y
) const 
 647         *x 
= m_xScrollPosition
; 
 649         *y 
= m_yScrollPosition
; 
 652 void wxScrolledWindow::DoCalcScrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 655     GetViewStart (& xs
, & ys
); 
 658         *xx 
= x 
- xs 
* m_xScrollPixelsPerLine
; 
 660         *yy 
= y 
- ys 
* m_yScrollPixelsPerLine
; 
 663 void wxScrolledWindow::DoCalcUnscrolledPosition(int x
, int y
, int *xx
, int *yy
) const 
 666     GetViewStart (& xs
, & ys
); 
 669         *xx 
= x 
+ xs 
* m_xScrollPixelsPerLine
; 
 671         *yy 
= y 
+ ys 
* m_yScrollPixelsPerLine
; 
 674 int wxScrolledWindow::CalcScrollInc(wxScrollWinEvent
& event
) 
 676     int pos 
= event
.GetPosition(); 
 677     int orient 
= event
.GetOrientation(); 
 680     if (event
.GetEventType() == wxEVT_SCROLLWIN_TOP
) 
 682             if (orient 
== wxHORIZONTAL
) 
 683                 nScrollInc 
= - m_xScrollPosition
; 
 685                 nScrollInc 
= - m_yScrollPosition
; 
 687     if (event
.GetEventType() == wxEVT_SCROLLWIN_BOTTOM
) 
 689             if (orient 
== wxHORIZONTAL
) 
 690                 nScrollInc 
= GetVirtualSize().GetWidth() / m_xScrollPixelsPerLine 
- m_xScrollPosition
; 
 692                 nScrollInc 
= GetVirtualSize().GetHeight() / m_yScrollPixelsPerLine 
- m_yScrollPosition
; 
 694     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEUP
) 
 698     if (event
.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN
) 
 702     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEUP
) 
 704             if (orient 
== wxHORIZONTAL
) 
 705                 nScrollInc 
= -GetScrollPageSize(wxHORIZONTAL
); 
 707                 nScrollInc 
= -GetScrollPageSize(wxVERTICAL
); 
 709     if (event
.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN
) 
 711             if (orient 
== wxHORIZONTAL
) 
 712                 nScrollInc 
= GetScrollPageSize(wxHORIZONTAL
); 
 714                 nScrollInc 
= GetScrollPageSize(wxVERTICAL
); 
 716     if ((event
.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK
) || 
 717         (event
.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE
)) 
 719             if (orient 
== wxHORIZONTAL
) 
 720                 nScrollInc 
= pos 
- m_xScrollPosition
; 
 722                 nScrollInc 
= pos 
- m_yScrollPosition
; 
 725     if (orient 
== wxHORIZONTAL
) 
 727         if (m_xScrollPixelsPerLine 
> 0) 
 729             int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 730             if (max 
< 0) max 
= 0; 
 732             if ( (m_xScrollPosition 
+ nScrollInc
) < 0 ) 
 733                 nScrollInc 
= -m_xScrollPosition
; // As -ve as we can go 
 734             else if ( (m_xScrollPosition 
+ nScrollInc
) > max 
) 
 735                 nScrollInc 
= max 
- m_xScrollPosition
; // As +ve as we can go 
 738             m_targetWindow
->Refresh(); 
 742         if (m_yScrollPixelsPerLine 
> 0) 
 744             int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 745             if (max 
< 0) max 
= 0; 
 747             if ( (m_yScrollPosition 
+ nScrollInc
) < 0 ) 
 748                 nScrollInc 
= -m_yScrollPosition
; // As -ve as we can go 
 749             else if ( (m_yScrollPosition 
+ nScrollInc
) > max 
) 
 750                 nScrollInc 
= max 
- m_yScrollPosition
; // As +ve as we can go 
 753             m_targetWindow
->Refresh(); 
 759 void wxScrolledWindow::SetScrollPos( int orient
, int pos
, bool refresh 
) 
 761     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid window") ); 
 763     wxCHECK_RET( m_wxwindow 
!= NULL
, wxT("window needs client area for scrolling") ); 
 765     if (orient 
== wxHORIZONTAL
) 
 767         int max 
= (int)(m_hAdjust
->upper 
- m_hAdjust
->page_size 
+ 0.5); 
 768         if (max 
< 0) max 
= 0; 
 770         if (pos 
> max
) pos 
= 0; 
 771         if (pos 
< 0) pos 
= 0; 
 773         if (pos 
== (int)(m_hAdjust
->value
+0.5)) return; 
 774         m_hAdjust
->value 
= pos
; 
 778         int max 
= (int)(m_vAdjust
->upper 
- m_vAdjust
->page_size 
+ 0.5); 
 779         if (max 
< 0) max 
= 0; 
 781         if (pos 
> max
) pos 
= 0; 
 782         if (pos 
< 0) pos 
= 0; 
 784         if (pos 
== (int)(m_vAdjust
->value
+0.5)) return; 
 785         m_vAdjust
->value 
= pos
; 
 788     if (m_wxwindow
->window
) 
 790         if (orient 
== wxHORIZONTAL
) 
 792             // Just update the scrollbar, don't send any wxWidgets event 
 793             GtkHDisconnectEvent(); 
 794             gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" ); 
 799             // Just update the scrollbar, don't send any wxWidgets event 
 800             GtkVDisconnectEvent(); 
 801             gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" ); 
 807 void wxScrolledWindow::GtkVConnectEvent() 
 809     gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed", 
 810           (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 813 void wxScrolledWindow::GtkHConnectEvent() 
 815     gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed", 
 816           (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 819 void wxScrolledWindow::GtkHDisconnectEvent() 
 821     gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
), 
 822         (GtkSignalFunc
) gtk_scrolled_window_hscroll_callback
, (gpointer
) this ); 
 825 void wxScrolledWindow::GtkVDisconnectEvent() 
 827     gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
), 
 828         (GtkSignalFunc
) gtk_scrolled_window_vscroll_callback
, (gpointer
) this ); 
 831 bool wxScrolledWindow::Layout() 
 833     if (GetSizer() && m_targetWindow 
== this) 
 835         // If we're the scroll target, take into account the 
 836         // virtual size and scrolled position of the window. 
 839         CalcScrolledPosition(0,0, &x
,&y
); 
 840         GetVirtualSize(&w
, &h
); 
 841         GetSizer()->SetDimension(x
, y
, w
, h
); 
 845         return wxPanel::Layout();  // fall back to default for LayoutConstraints 
 848 // ---------------------------------------------------------------------------- 
 850 // ---------------------------------------------------------------------------- 
 852 // Default OnSize resets scrollbars, if any 
 853 void wxScrolledWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 855     if ( m_targetWindow
->GetAutoLayout() ) 
 857         wxSize size 
= m_targetWindow
->GetBestVirtualSize(); 
 859         // This will call ::Layout() and ::AdjustScrollbars() 
 860         SetVirtualSize( size 
); 
 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
);