1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/scrolwin.cpp 
   3 // Purpose:     wxScrolledWindow implementation 
   4 // Author:      Robert Roebling 
   5 // Modified by: Ron Lee 
   6 //              Vadim Zeitlin: removed 90% of duplicated common code 
   9 // Copyright:   (c) Robert Roebling 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 // ============================================================================ 
  15 // ============================================================================ 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  28 #include "wx/scrolwin.h" 
  29 #include "wx/gtk/private.h" 
  31 // ============================================================================ 
  33 // ============================================================================ 
  35 // ---------------------------------------------------------------------------- 
  36 // wxScrollHelper implementation 
  37 // ---------------------------------------------------------------------------- 
  39 void wxScrollHelper::SetScrollbars(int pixelsPerUnitX
, int pixelsPerUnitY
, 
  40                                    int noUnitsX
, int noUnitsY
, 
  45     GetViewStart(& xs
, & ys
); 
  47     int old_x 
= m_xScrollPixelsPerLine 
* xs
; 
  48     int old_y 
= m_yScrollPixelsPerLine 
* ys
; 
  50     m_xScrollPixelsPerLine 
= pixelsPerUnitX
; 
  51     m_yScrollPixelsPerLine 
= pixelsPerUnitY
; 
  53     m_win
->m_scrollBar
[wxWindow::ScrollDir_Horz
]->adjustment
->value 
= 
  54     m_xScrollPosition 
= xPos
; 
  55     m_win
->m_scrollBar
[wxWindow::ScrollDir_Vert
]->adjustment
->value 
= 
  56     m_yScrollPosition 
= yPos
; 
  58     // Setting hints here should arguably be deprecated, but without it 
  59     // a sizer might override this manual scrollbar setting in old code. 
  60     // m_targetWindow->SetVirtualSizeHints( noUnitsX * pixelsPerUnitX, noUnitsY * pixelsPerUnitY ); 
  62     int w 
= noUnitsX 
* pixelsPerUnitX
; 
  63     int h 
= noUnitsY 
* pixelsPerUnitY
; 
  64     m_targetWindow
->SetVirtualSize( w 
? w 
: wxDefaultCoord
, 
  65                                     h 
? h 
: wxDefaultCoord
); 
  67     // If the target is not the same as the window with the scrollbars, 
  68     // then we need to update the scrollbars here, since they won't have 
  69     // been updated by SetVirtualSize(). 
  70     if (m_targetWindow 
!= m_win
) 
  77         int new_x 
= m_xScrollPixelsPerLine 
* m_xScrollPosition
; 
  78         int new_y 
= m_yScrollPixelsPerLine 
* m_yScrollPosition
; 
  80         m_targetWindow
->ScrollWindow( old_x 
- new_x
, old_y 
- new_y 
); 
  84 void wxScrollHelper::DoAdjustScrollbar(GtkRange
* range
, 
  94     if (pixelsPerLine 
> 0 && winSize 
> 0 && winSize 
< virtSize
) 
  96         upper 
= (virtSize 
+ pixelsPerLine 
- 1) / pixelsPerLine
; 
  97         page_size 
= winSize 
/ pixelsPerLine
; 
  99         *linesPerPage 
= page_size
; 
 103         // GtkRange won't allow upper == lower, so for disabled state use [0,1] 
 104         //   with a page size of 1. This will also clamp position to 0. 
 111     GtkAdjustment
* adj 
= range
->adjustment
; 
 112     adj
->step_increment 
= 1; 
 113     adj
->page_increment 
= 
 114     adj
->page_size 
= page_size
; 
 115     gtk_range_set_range(range
, 0, upper
); 
 117     // ensure that the scroll position is always in valid range 
 122 void wxScrollHelper::AdjustScrollbars() 
 125     m_targetWindow
->GetVirtualSize(&vw
, &vh
); 
 128     const wxSize availSize 
= GetSizeAvailableForScrollTarget( 
 129         m_win
->GetSize() - m_win
->GetWindowBorderSize()); 
 130     if ( availSize
.x 
>= vw 
&& availSize
.y 
>= vh 
) 
 135         // we know that the scrollbars will be removed 
 136         DoAdjustHScrollbar(w
, vw
); 
 137         DoAdjustVScrollbar(h
, vh
); 
 142     m_targetWindow
->GetClientSize(&w
, NULL
); 
 143     DoAdjustHScrollbar(w
, vw
); 
 145     m_targetWindow
->GetClientSize(NULL
, &h
); 
 146     DoAdjustVScrollbar(h
, vh
); 
 149     m_targetWindow
->GetClientSize(&w
, NULL
); 
 152         // It is necessary to repeat the calculations in this case to avoid an 
 153         // observed infinite series of size events, involving alternating 
 154         // changes in visibility of the scrollbars. 
 155         // At this point, GTK+ has already queued a resize, which will cause 
 156         // AdjustScrollbars() to be called again. If the scrollbar visibility 
 157         // is not correct before then, yet another resize will occur, possibly 
 158         // leading to an unending series if the sizes are just right. 
 159         DoAdjustHScrollbar(w
, vw
); 
 161         m_targetWindow
->GetClientSize(NULL
, &h
); 
 162         DoAdjustVScrollbar(h
, vh
); 
 166 void wxScrollHelper::DoScrollOneDir(int orient
, 
 171     if ( pos 
!= -1 && pos 
!= *posOld 
&& pixelsPerLine 
) 
 173         m_win
->SetScrollPos(orient
, pos
); 
 174         pos 
= m_win
->GetScrollPos(orient
); 
 176         int diff 
= (*posOld 
- pos
)*pixelsPerLine
; 
 177         m_targetWindow
->ScrollWindow(orient 
== wxHORIZONTAL 
? diff 
: 0, 
 178                                      orient 
== wxHORIZONTAL 
? 0 : diff
); 
 184 void wxScrollHelper::DoScroll( int x_pos
, int y_pos 
) 
 186     wxCHECK_RET( m_targetWindow 
!= 0, _T("No target window") ); 
 188     DoScrollOneDir(wxHORIZONTAL
, x_pos
, m_xScrollPixelsPerLine
, &m_xScrollPosition
); 
 189     DoScrollOneDir(wxVERTICAL
, y_pos
, m_yScrollPixelsPerLine
, &m_yScrollPosition
); 
 192 // ---------------------------------------------------------------------------- 
 193 // scrollbars visibility 
 194 // ---------------------------------------------------------------------------- 
 199 GtkPolicyType 
GtkPolicyFromWX(wxScrollbarVisibility visibility
) 
 201     GtkPolicyType policy
; 
 202     switch ( visibility 
) 
 204         case wxSHOW_SB_NEVER
: 
 205             policy 
= GTK_POLICY_NEVER
; 
 208         case wxSHOW_SB_DEFAULT
: 
 209             policy 
= GTK_POLICY_AUTOMATIC
; 
 212         case wxSHOW_SB_ALWAYS
: 
 213             policy 
= GTK_POLICY_ALWAYS
; 
 220 } // anonymous namespace 
 222 void wxScrollHelper::DoShowScrollbars(wxScrollbarVisibility horz
, 
 223                                       wxScrollbarVisibility vert
) 
 225     GtkScrolledWindow 
* const scrolled 
= GTK_SCROLLED_WINDOW(m_win
->m_widget
); 
 226     wxCHECK_RET( scrolled
, "window must be created" ); 
 228     gtk_scrolled_window_set_policy(scrolled
, 
 229                                    GtkPolicyFromWX(horz
), 
 230                                    GtkPolicyFromWX(vert
));